Некоторые картинки не загружаются из РФ и РК, используйте VPN.
Показаны сообщения с ярлыком Mikrotik. Показать все сообщения
Показаны сообщения с ярлыком Mikrotik. Показать все сообщения

вторник, 8 августа 2023 г.

Mikrotik ikev2 ошибка сопоставления групповой политики

Настроил тут на Mikrotik IKEv2, у меня работает даже в sandbox, а у одного из сотрудников вылетает сабж. При этом в логе на Mikrotik ничего, может показаться что клиент даже не инициирует подключение, но мы то умные, идем в System-Logging и добавляем ipsec. Снова пробуем подключиться и сразу видим вот такую картину:


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



Вот и все

пятница, 21 июля 2023 г.

Mikrotik script rename/copy file

Наибанальнейшая задача, связанная с тем фактом, что Mikrotik подставляет расширение txt практически к любому файлу. Простой консольный вариант:

/tool fetch mode=ftp user=FTP_USER password=Parol src-path=$SrcFile dst-path=$DstFile

Для работы требуется включить FTP, для безопасности можно ограничить адресом 127.0.0.1:

add action=accept chain=input dst-address=127.0.0.1 dst-port=80,21 protocol=tcp

Также требуется создать пользователя с ограничением по адресу и связать с группой с правами FTP,read,write

/user group add name=ftp policy="ftp,read,write,!local,!telnet,!ssh,!reboot,!policy,!test,!winbox,!password,!web,!sniff,!sensitive,!api,!romon,!dude,!tikapp"
/user add address=127.0.0.1/32 group=ftp name=FTP_USER

А это простенькая функция:

# Example: $RenameCopyFile SrcFile="File.ovpn.txt" DstFile="File.ovpn" ItCopy=true
 
:local RenameCopyFile do={
	do {
		 [/tool fetch mode=ftp user=User password=Parol url="ftp://127.0.0.1/$SrcFile" dst-path=$DstFile as-value]
	} on-error={
		:put ("Failed to copy/rename file from \"$SrcFile\"")
		:put ("Check settings ftp. \r\nImportant: \r\n\tftp - enable, \r\n\tport 21 open from 127.0.0.1, \r\n\tcreate user with permisson: \r\n\t\tftp,\r\n\t\tread,\r\n\t\twrite \r\n\tand allowed address=127.0.0.1")
		return 0
	}
	if ($ItCopy=false) do={
		/file remove $SrcFile
		:put ("Success to rename file to \"$DstFile\"")
	} else {
		:put ("Success to copy file to \"$DstFile\"")
	}
}

Функция не делает всяких проверок на наличие файла и правил, полагаемся на пользователя. Также внимательный читатель обратит внимание на то, что в первом примере использовался scr-path, а в этом примере используется url, так сделано для того, чтобы скрыть вывод команды (as-value)

Параметр ItCopy указывает на то, что мы хотим - скопировать или переименовать/переместить файл. Если указать true, то исходный файл удален не будет. Т.о. можно скопировать файл размером более 4096

вторник, 18 июля 2023 г.

Mikrotik script copy file from internal memory to internal memory

 Задача банальная, но сначала она ввела меня в ступор, ибо copy в /file нету. А решение банальное - в set contents направить get contents

/file set myFile.txt contents=[/file get SourceFile.txt contents]

Также не стоит забывать про ограничение на размер переменной 4096 байта, а в данном примере мы как раз сталкиваемся с этим ограничением

Плюс к этому, файл приемник должен существовать. Оригинальная инструкция с сайта mikrotik:

/file print file=myFile
/file set myFile.txt contents=""

Ошибки тут нет, к файлам добавляется расширение txt и это не поправить.

Но на wapLTE получаю ошибку no such item, так как файл не успевает создаться до выполнения второй строки. Добавляем паузу

/file print file=myFile
delay 2
/file set myFile.txt contents=""

Таким образом наш скрипт будет выглядеть так:

:local FileName "MyFile.txt"
:local Contents ([/file get SourceFile.txt contents])
/file print file=$FileName
delay 2
if ([:len [/file find where name=$FileName]]>0) do={
	/file set $FileName contents=$Contents
}else={
	:put "File not found"
}

А как дописать в тот же файл?

/file set myFile.txt contents=([/file get myFile.txt contents] . "\r\nBlalalala")

но и здесь работает ограничение 4096, поэтому слить 2+ файла <4096 bite в один файл >4096 не получится

А как скопировать или сформировать большой файл?, ограничение 4096 байт распространяется только на размер переменной

Вот тут можно провернуть фокус execute + put

:local mergeFile "
:local contents [/file get MyFile.txt contents]
:put \$contents
:put \$contents
:put \$contents
:put \$contents
"
:execute script=$mergeFile file=test

Но и в этом примере есть ограничение - источник не может быть больше 4096, плюс к имени файла будет добавлено расширение txt (переименовываем файлы).

Если нужно просто скопировать большой файл, то можно выполнить трюк с переименовыванием, исправил скрипт 16/09/2023.

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

четверг, 6 июля 2023 г.

RouteOS Пересылка SMS на другой номер

Есть wapLTE и симка, задача пересылать смс. Самый простой способ:

:local new_num 8985756575
:foreach message in=[/tool sms inbox print as-value] do={

	:local idSMS ($message->".id")
	:local phoneNumber ($message->"phone")
	:local TextMessage ($message->"message") 
	:local FullMessage "Phone: $phoneNumber\nSMS: $TextMessage"
	/log  info message=$FullMessage 
	/tool sms send lte1 phone-number=$new_num message=$FullMessage
	/tool sms inbox remove numbers=$idSMS
	:delay 1000ms
}

Никакой универсальности, что получил, то переслал. Естественно UTF8 мимо крокодилит знаками вопроса. Для пересылки сообщений из банка, мне кажется такого достаточно.

Добавляем в планировщик, время ставим как удобно.

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

Есть вариант с перекодировкой проще и телеграм отправляет здесь, но смс кириллицей не отправляет

пятница, 19 мая 2023 г.

Mikrotik SSH private key for authorization on other ssh services

Запускаем SSH Keygen и генерируем ключ по кнопке Generate, бешено дергаем мышкой, дабы  ускорить процесс (всякие настройки не трогаем).

Сохраняем публичную часть - через Save + конвертация:
Как видно из скриншота, это можно сделать ручками
Или сразу копируем из окна PuttyGEN:

Экспортируем закрытую часть в старом формате:

Я назвал файлы my.ppk и my.pub, перебрасываем наши файлы на Mikrotik и импортируем

Внимание!!!

Пользователь указывается тот, из под которого будет инициировано подключение ssh к удаленному ресурсу, также следует учесть пользователя под которым будет работать задание в шедуллере Mikrotik. После чего закидываем (простым копипастом содержимого my.pub, там должна быть одна строчка) открытую часть на сервер где требуется авторизация со стороны Mikrotik в файл /home/username/.ssh/authorized_keys (/root/.ssh/authorized_keys - для авторизации под рутом - оч плохая идея)

Собственно все, теперь можно авторизоваться под ssh ключами:

пятница, 28 апреля 2023 г.

Mikrotik переброс DNS запросов на другой Mikrotik

Задача пинговать кастомные зоны на vpn клиентах (openvpn).

При помощи модифицированного скрипта подготовки ovpn файлов я формирую следующую конфигурацию:

client
dev tun
proto tcp-client
remote vpn.mysite.ru
nobind
persist-key
persist-tun
auth-nocache
ca [inline]
cert [inline]
key [inline]
askpass 1.cfg
auth-user-pass stdin
remote-cert-tls server
pull-filter ignore redirect-gateway
dhcp-option DNS 10.111.11.1
dhcp-option ADAPTER_DOMAIN_SUFFIX skzloc,lokihome
route 10.11.11.0 255.255.255.0 10.111.11.1
route 10.110.1.0 255.255.255.0 10.111.11.1
cipher AES-256-CBC
tls-cipher TLS-RSA-WITH-AES-256-CBC-SHA
auth SHA1

среда, 15 февраля 2023 г.

OpenVPN ошибка GET INST BY VIRT

Задача из разряда объединение сетей, а точнее - через клиента получить доступ к сети самого клиента. Так как так мы решали задачу доступа сервера Zabbix к узлам, то и  роль VPN сервера упала на сервер Zabbix. В качестве поставщика VPN выбрали OpenVPN. В качестве клиента выступает Mikrotik CRS326-24S+2Q+RM

Для понимания общей схемы, на коленке вот такую штуку нарисовал, сразу понятно, что косяк может возникнуть в любом месте

воскресенье, 25 декабря 2022 г.

Mikrotik script подготовка конфигурационного файла OVPN

У pfSense есть забавная штука - экспорт конфигурации OpenVPN, такой штуки нет на Mikrotik. Я бы мог использовать pfSense или openSense, но они мне не нравятся, а в некоторых случаях сложны для настройки. Так как в одном из проектов мне волей-неволей придется создавать новых пользователей openVPN, я решил максимально автоматизировать процесс экспорта конфигурации и описал скрипт. Скрипт:

  1. запрашивает необходимые данные
  2. создает пользователя
  3. создает и подписывает сертификат
  4. создает структуру папок
  5. создает все необходимые файлы в этой структуре
  6. экспортирует сертификат
  7. формирует и выгружает файл конфигурации
Остается только нажать на каталог правой клавишей - сохранить, скопировать конфиг и структуру каталогов в каталог openVPN (в зависимости от типа либо config, либо config-auto (требуется установка службы))
Да, сам сервер уже должен быть настроен! По-умолчанию в качестве адреса сервера openVPN берется Identity устройства. 

Запись из июля 2023 года, скрипт формирует структуру каталогов из-за ограничения переменной в 4096 байта, но я случайно нашел обходной вариант, который позволяет слить файлы в один большой - самый последний пример.

суббота, 24 декабря 2022 г.

Mikrotik script Ввод от пользователя

 Порой есть задача - запросить данные от пользователя, оказывается в Mikrotik такое тоже возможно. Описал простенькую функцию с параметрами:

  • QstUser - Текст вопроса
  • VarName - Имя переменной куда будет помещено введенное значение
  • DefaultValue - Значение по-умолчанию (на случай пустого ввода)
  • LenValue - Минимальная длина ввода (например pass-phrase для экспорта сертификата не может быть меньше 8 символов)
# Example:
# :global UserName ""
# $PromtInput QstUser="\r\nInsert new username" VarName="UserName" DefaultValue=UserX LenValue=4
:local PromtInput do={
	:local readinput do={:return}
	if ($LenValue>0) do={
		:set $QstUser ("$QstUser. Minimum length $LenValue simbols")
	}
	if ([:len $DefaultValue]>0) do={
		:set $QstUser ("$QstUser. \r\n(default - $DefaultValue)")
	}
	:put ("$QstUser:")
	:local UserPromt [$readinput]
	if ([:len $UserPromt]>0) do={
		[:parse "global $VarName;:set $VarName $UserPromt"]
		if (($LenValue>0) and [:len $UserPromt]<$LenValue) do={
			:error message="You entered only $[:len $UserPromt] symbols instead of $LenValue minimum required. Stop program"
		}
	} else={
		if  ([:len $DefaultValue]>0) do={
			[:parse "global $VarName;:set $VarName $DefaultValue"]
		} else={
			:error message="You didn't enter anything. Stop program"
		}
	}
}

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

понедельник, 19 декабря 2022 г.

Mikrotik script обход параметров функции

 Предположим ситуация - необходимо обработать N слов, каждое слово является позиционным параметром некоей функции, сколько слов может быть на входе мы не знаем, но предполагаем что не больше 10. Каким образом обработать параметры? Сначала я подумал о преобразовании текста в код в цикле и обработки его при помощи :parse или :execut как предлагает доблестный rextended:

:global variablename "test"

# Create a global variable using the name inside "variablename" and set the value (or update the value if is already defined)
[:parse ":global $variablename \"REX1\""]
# after "parse" the variable exist and can be displayed
:put $test

# Set a value of variable with name defined inside "variablename" (or simply apply previous "parse" command)
[:parse "global $variablename;:set $variablename \"REX2\""]
:put $test

# For read the value, of a variable with name defined inside "variablename", and put it inside another global or local declared variable:
:global testx [[:parse ":global $variablename; :return \$$variablename"]]
:put $testx

# For read the value, of a variable with name defined inside "variablename", simply for put the value on terminal:
:put [[:parse ":global $variablename; :return \$$variablename"]]

Но, в случае с позиционными параметрами, вариант не прокатил, чет думал-думал (внутренний диалог):

"Вот бы знать сколько их там, в bash то мы знаем"
"Да какая разница сколько их там, все равно цикл с формированием имени переменной не использовать"
"Тогда забей и юзай условной блок с :return"
"Нет, это решение громоздкое и не красивое!....Эврика!, рекурсия со сдвигом параметров!"

Mikrotik script Создать каталог

 Решил я описать скрипт по логике которого, нужно было раскидывать файлы по папкам, и тут выясняется что нельзя взять и создать каталог О_О.

В интернетах предлагают такой вариант

/tool fetch dst-path=MyPath/xxx url="http://127.0.0.1/"

Или такой

/tool fetch dst-path=MyPath/xxx url="http://google.com/"

Но у меня не работает такое, в такой вариант прокатил

/tool fetch dst-path=MyPath/xxx url="https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"

Чтобы файл не скачивался, вместо xxx ставим точку

/tool fetch dst-path=MyPath/. url="https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"

Поддиректории через слеш

/tool fetch dst-path=MyPath/subFolder/. url="https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"

Но такой вариант мне не нравится из-за ненадежности источника скачивания, и я нашел вариант через SMB

/ip smb shares add name=test directory=MyPath
/ip smb shares remove [/ip smb shares find where name=test]

Т.о. для создания структуры, можно описать таким образом

суббота, 10 декабря 2022 г.

Mikrotik script ssh not execute

Дорабатывая старый проект я столкнулся с проблемой в топике. Нужно было отправить wol не только с нашего роутера, но и с роутера в другом широковещательном сегменте сети. Скрипт успешно отрабатывал после мытарств, но напрочь отказывался работать при запуске из блока on up профиля ppp. В итоге виновник был найден - разрешения, из-за этого мне пришлось напичкать скрипт выводами в лог (обновленный вариант выложил в старый пост) и описать функцию логирования. Что странно, на моменте тестирования скрипт выполнялся со всеми включенными разрешениями и под пользователем с полными правами, на обоих аппаратах, все равно пришлось установить галку "don't require permissions" в настройках скрипта!

Mikrotik script простенькая функция логирования

 Задача банальна - писать в лог тогда. когда мне это удобно + писать в вывод (на случай ручного запуска скрипта). Первый вариант был в другом скрипте, в новой старой задаче мне понадобилась эта штука, но пришлось доработать.

# Func loging. For debug. Error write forever, other only of WriteLog =>0 (0 1 2 - level logging), setup up of global var
# $TYPE - topics (error,info)
# $LEVEL - level logging
# 	0 only error
#	1 main
#	2 all
# $MESSAGE - text message
# Example
# 	$Logging MESSAGE=("My text") TYPE="info"  LEVEL=2
# for use in func use global context and declared WriteLog
# Exmaple
# :global WriteLog
# $Logging MESSAGE=("My text $codeExit") TYPE="info"  LEVEL=2

:global WriteLog

:global Logging do={
	:global WriteLog
	:local TextMessage ("PlugUser => ".$MESSAGE)	
	:if ($LEVEL<=$WriteLog) do={
		:if ($TYPE="info") do={ :log info message=($TextMessage) }
		:if ($TYPE="error") do={ :log error message=($TextMessage) }
	}
	:put $TextMessage
}

Тут фокус в возможности указания уровня логирования. Не забываем в конце удалять глобальную переменную и правила использования функция и переменных в функциях тут

Mikrotik script ssh command log variable

 Вот такая странная тема. Мне нужно было передать 2 команды в ssh-exec со значениями из переменных. Собственно с первой командой проблем не было, а вторая либо не выполнялась, либо писала пустоту в лог (команда логирования). Собственно весь фокус в экранировании при использовании синтаксиса :log info message=("")

/system ssh-exec user=adm address=10.21.0.1 command=("tool wol mac=$macAddr interface=bridge1_LAN; :log info message=(\"$RemoteMessage\")")

Как видим, у нас 2 переменных - $macAddr и $RemoteMessage в двух командах, и оно прекрасно выполняется

/system ssh-exec user=vint address=10.21.0.1 command=("tool wol mac=$macAddr interface=bridge1_LAN; :log info message=(\"Send magic packet on mac:$macAddr, for user $patern\")")

Такой вариант тоже прокатывает, но сложнее читать без правильной подсветки

/system ssh-exec user=vint address=10.21.0.1 command=("tool wol mac=$macAddr interface=bridge1_LAN; :log info message=(Send magic packet on mac:$macAddr, for user $patern)")

А вот без кавычек не сработает, вернет пустоту

понедельник, 5 декабря 2022 г.

Keepass клик по URL - открытие Winbox

 В Keepass можно настроить открытие той или иной программы по клику на URL, и передать в программу параметрами некоторые данные. Мне захотелось настроить это дело для WinBox. сам Winbox имеет порядковые параметры:

winbox64.exe ADDRESS USERNAME PASSWORD

Как видим, ничего сложного в открытии программы с предопределенными параметрами, теперь добавим это дело в настройки KeePass:


cmd://"%PROGRAMFILES%\Winbox\winbox64.exe" {BASE:RMVSCM} {USERNAME} {PASSWORD}

Предполагается что сам Winbox (x64) находится по пути "\Program Files\Winbox\" и назывется winbox64.exe

Все, теперь в поле URL пишем winbox:\\address и оно будет работать

вторник, 29 ноября 2022 г.

Mikrotik Типа Jump server

 Для доступа к конечному оборудованию (сервер ssh/rdp/https, сетевое оборудование и т.д. )использую как VPN так и белые списки (iptables and etc). Т.к. гарантировать работу сразу нескольких туннелей представляется сложным, я вынужден, в некоторых случаях (выход с неразрешенного ip), подключаться к конечной точке через промежуточную, подключенную через VPN. Порой хоуп получается тройной или даже четверной вложенности. По сути это получается что-то типа ssh-jump-server. Это очень неудобно для вариантов RDP или же банального веб интерфейса. 

Последние два месяца я нахожусь за пределами физического расположения разрешенных IP адресов, и т.к. основной IP у меня белый динамический, я вынужден прописывать по новой каждый раз. Это противоречит цели белых списков, т.к. мы не знаем кому потом будет принадлежать этот ip, так еще и вечные трудозатраты на настройку.

Мне тут предложили использовать SSO и keykloak, но мне показалось что это не то что надо, плюс очень громоздко.

понедельник, 7 ноября 2022 г.

Mikrotik script как скрипт управления D-Link`ом по SNMP писали

Есть у меня сервер, с воткнутым в него свистком, который принимал смс. По крону смски проверялись и выполнялись определенные операции при поступлении управляющих кодов. Последнее время модем начал глючить, да и баланс уже год не показывает и сервер состарился, а тут еще и wAP LTE освободился. Я точно знаю что можно с него (аппарат на базе R11e-LTE) читать  и отправлять SMS, и даже USSD запросы.

Mikrotik Script Error: cannot substract nothing from string

 Сижу туплю, что за ошибка, ведь в консоли этот фокус прокатил. Добавил:

:put [:typeof $MyVar]

получил, как и ожидал, ответ:

array

- так что ты тогда хочешь?! - негодовал я

В итоге увидел случайно, что я не дописал извлечение элемента массива, я написал так:

:put ($MyVar-"exit-code")

а надо:

:put ($MyVar->"exit-code")

Глаз на столько замылился, что спустя 100+ таких конструкций, перестал замечать

воскресенье, 6 ноября 2022 г.

Mikrotik script проверить наличие другого экземпляра и вызвать исключение

 На bash мы можем заглянуть в диспетчер задач (ps) и найти процесс нашей программы, прежде чем ее запускать (здесь рассматривал). На Mikrotik же такого нету, приходится извращаться. Зачем это надо?, если один из экземпляров программы по какой то причине зависнет, а еще он использует глобальные переменные, то мы можем получить неожиданный результат, поэтому лучше избегать таких коллизий. 

Сама идея проста - проверить некоторую глобальную переменную, которую создаем после проверки, но у Mikrotik свои заморочки и приходится изгаляться:

# ищем среди глобальных переменных. ошибки здесь не будет, либо "", либо id
# в отличии от поиска через get, там и ошибки, и "не моментальное заполнение" списка,
# т.е. первый экземпляр висит уже 10  сек, а переменные через get еще отсутствуют
:if ([/system script environment find where name=RunProgram]!="") do={
	:log error ("There is another instance of the program running, exit")
	:error message="There is another instance of the program running, exit"
}
# объявляем глобальную переменную
:global RunProgram true
...
...
...
# уничтожаем переменную
:set RunProgram

Есть более изящный вариант - проверка в текущих заданиях:

:local scriptname "MyScript"
:if ([:len [/system script job find script=$scriptname]] > 0) do={
	:log error "There is another instance of the program running, exit"
    :error message="There is another instance of the program running, exit"
}