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

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

"- Если вы возьметесь лечить больного и он умрет, вы будете казнены!
- А если он выздоровеет?
- В таком случае вы также будете казнены!
- Не велика разница?
- В случае смерти больного карается невежество, в случае выздоровления - дерзость. В обоих случаях вас ждет виселица."

пятница, 30 декабря 2022 г.

Nginx условие в конфигурационном файле

Делал мониторинг nginx zabbix`ом и тут возникла проблема, сайт перенаправляет всех на https, а проверку не надо перенаправлять, как же сделать так, чтобы перенаправление работало не всегда?

server{
    listen          80;
    server_name     site.pro www.site.pro *.site.pro;
    # Enable php-fpm status page (for ZABBIX PHP-FPm HTTP)
    location ~ ^/(status|ping)$ {
        access_log off;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_pass 127.0.0.1:9000;
    }
    # Enable php-fpm status page (for ZABBIX PHP-FPm HTTP) END
    # ADD conditional block
    if ($request_uri !~* "^/(status|ping)$") {
        return 301  https://$host$request_uri;
    }
}

~* - равно регулярке без учета регистр
!~* - не равно регулярке без учета регистр
= - равно правой части
!= - не равно правой части

Во всех условиях, кроме регулярок, использовать знак доллара ($) нельзя, он будет интерпретирован как переменная. Ну или экранируем

Подробнее

четверг, 29 декабря 2022 г.

 Порой снится всякая дичь, иногда занимательно и интересно, особенно если предположить что сон - это наша жизнь в другой вселенной (теория мульти вселенных). Сегодня что именно снилось не помню, но в какой-то момент вспыхнул кадр из сна - женская рука покровительственно лежит на плече сидящего человека... может не покровительственно, а ...смирение (?)... нет... нет слов... как-будто говоря - "смотри, я ..." ... и опять нет слов, чтобы описать. Лиц я не вижу, но как-будто знаю кто это (АМ). Но главное в этой руке - на безымянном пальце обручальное кольцо, классическое, без выкрутасов, над ним вытатуирована точка, а под ним символ бесконечности. В остаточных ощущениях от вспышки картинки чувствуется ответ на вопрос - что значит эта комбинация, но в этой вселенной я так и не понял значения. Также стоит отметить, что это была левая рука, что не характерно для рожденных в России.



"Учился всему понемногу, а потому, как это обычно бывает в таких случаях, не знал ничего!"

вторник, 27 декабря 2022 г.

 

Омлет с овощами

Windows Port forwarding силами ОС

Появилась задача - перебросить пакеты с порта на VPN интерфейсе сервера на другой VPN интерфейс, при этом на сервере работает RRAS. Силами RRAS не получилось, так интерфейс "внутренний" не имеет такой возможности, а вот netsh portproxy справился на ура:

netsh interface portproxy add v4tov4 listenaddress=10.10.10.2 listenport=6604 connectaddress=192.168.80.1 connectport=6604

А вот так можно удалить проброс:

netsh interface portproxy delete v4tov4 listenaddress=10.10.10.2 listenport=6604

А вот так можно проверить список пробросов:

netsh interface portproxy show all

Контроль:

netstat -ano | findstr :6604

Обязательно должна быть включена служба IP Helper:

sc query iphlpsvc

Отметил, что после перезагрузки правило остается, но не работает (порт не слушается). Может быть это связано с тем, что интерфейс, а соответственно и маршрут, появляются позже. В следующий раз проверю, может достаточно перезагрузить службу, тогда накинем отложенный шедуллер, а может вообще if up для службы OpenVPN бахнем

Источник

Второй источник

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

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



А теперь самое веселое, эта плюшка не нужна, если SMART карта поддерживается определенными криптопровайдерами, тогда можно использовать SMART карту сразу на RDP сервере

Версия 5.0.12600 - не сертифицирована, поэтому я использовал вариант с донастройкой и у меня реально заработало О_О

воскресенье, 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"
		}
	}
}

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

"Жаркое с говядкой"

 

"Ешь, не то я вышвырну тебя за дверь, вместе с твоей негодницей!"

Урсус - очень интересный персонаж...

 На фоне мальчика 99,9% людей - нелюди, и я в том числе...

"Похлебка из рыбы"
"Похлебка для рыбы" - поправил его доктор


пятница, 23 декабря 2022 г.

 Человек стремится идти по модели упрощения во всем, в работе, в отдыхе, в домашних делах и в искусстве. Вот и Гюго здесь и в "Отверженные" уделяет много времени отсылкам и описаниям. Меня самого иногда заносит, но сколько строк ушло на описание подвешенного на цепи мертвеца. А начало меня сначала отправило не пойми куда и я засомневался в художественности произведения, но здесь еще большую роль сыграл тот факт, что 36 часов сна ни в одном глазу, а умиротворение и безделье только усугубили притяжение в царство Морфея


В какой-то момент 1С сообщила: "Братан, твой ключ в тыкву превратится лишь бить начнут куранты". Я был сильно удивлен, ибо ключ до февраля с хвостиком, проверил, оказывается и вправду, они только до 01 (пысы, постановление о продлении было 19 декабря). Копаясь на разных сайтах узнал что в Байконуре есть налоговая РФ, где можно сделать ЭЦП на ИП или ООО. Также там есть представительство контура, где можно купить токен с отметкой ФСТЭК. Собственно встал вопрос о посещении сего города. Но попасть туда можно только по пропуску, поэтому забил. Это было не то в октябре, не то в ноябре. А в конце ноября нашлись люди, которые могут сделать пропуск туристический, связался и таки заказал и ключ и пропуск. 
Тут я долго сидел и думал, как совершить эту поездку: на машине, на поезде, на самолете. В итоге поезд выиграл. Купил билеты на сайте КТЖ (выезд 15, прибытие 16, убытие 16го, прибытие обратно 17/12). Все вроде гладко, но нет. В билетах время убытия указано по времени Астаны (ЧП +4), я в Атырау (ЧП +6), а Байконур в ЧП +6. Почему в билетах указано левое время, без пометок? В итоге я опоздал на поезд на час.

Расстроился, и пошел домой. Заказал новые билеты и тут опять ничего про ЧП не сказано! Заказал на 21 убытие и 23 возврат. Билеты надо подобрать так, чтобы приехать утром, а уехать этим же днем.

четверг, 22 декабря 2022 г.

 Мда, развязка неожиданная, или ожидаемая??, Но конец вызвал у меня дежавю, не то я видел конкретно это, не то что-то похожее...

понедельник, 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]

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

пятница, 16 декабря 2022 г.

Bash Console Script Фигурные скобки

"А так можно было?" - подумал я увидя такую конструкцию:

user@server:~$ mv /etc/postfix/{canonical,sender_relay,sasl_passwd} /etc/postfix/private/

Или так (переимновать без ввода полного пути)

user@server:~$ mv /etc/postfix/main.cnf{,.back}

Или так (создать копию без повторного ввода всего пути)

user@server:~$ cp /etc/postfix/main.cnf{,.back}
user@server:~$ ls /etc/postfix/main*
/etc/postfix/main.cf  /etc/postfix/main.cf.back  /etc/postfix/main.cf.db  /etc/postfix/main.cf.proto  /etc/postfix/main.cf.proto.db  /etc/postfix/main.cf.save

С того момента я каждый раз тратил много времени на попытку вспомнить конструкцию и вот решил устаканить в своей голове фигурные скобки в консоли линукс-подобных систем. При повседневных операциях бывает необходимо повторить одно действие несколько раз и как же бесит когда не можешь упростить. Перейдем к примерам - скопировать из каталогов несколько разных файлов можно разными способами:

user@server:~$ ls ~/test
folder_1 folder_2 file_1 file_2 file_1_bak file_2_bak

user@server:~$ cp ~/test/file_1 ~/test/file_1_bak /new_folder
user@server:~$ ls /new_folder
file_1 file_1_bak

user@server:~$ rm /new_folder/*
user@server:~$ cp ~/test/file_1* /new_folder
user@server:~$ ls /new_folder
file_1 file_1_bak

user@server:~$ rm /new_folder/*
user@server:~$ cp ~/test/file_{1,1_bak} /new_folder
user@server:~$ ls /new_folder
file_1 file_1_bak

user@server:~$ rm /new_folder/*
user@server:~$ cp ~/test/file_1{,_bak} /new_folder
user@server:~$ ls /new_folder
file_1 file_1_bak

суббота, 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)")

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

пятница, 9 декабря 2022 г.

 Приснилось что я дослушал произведение и история у Салливана младшего не отличилась от истории Салливана старшего, собственно можно было не продолжать...

четверг, 8 декабря 2022 г.

" - Зайди к нам, мне нужна голова Нептуна - говорит О.

Я в непонятках - что зачем ... Прихожу, при этом со мной идут мой старый сотрудник и новый, а заходим мы не в то привычное помещение (квартира), а в двухэтажный дом. Надо заметить что О - руководитель и владелец фирмы по бух сопровождению.

- Какая голова Нептуна?
- Мы тут с девочками днем бухгалтерию, а ночами делаем гипсовые головы. Мне нужна голова Нептуна, будем снимать слепок с твоей головы
- Но я не похож на Нептуна
- Ничего, нам подойдет"

Самое забавное в этом сне то, что проснувшись я увидел сообщение от О, а она давно не писала...

понедельник, 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 и оно будет работать

Есть косяки, но это лучшее из всех трех произведений...

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

 

Картошечка и соте из овощей. Соте просто бомба, даже вторую порцию навернул

"Еще один писатель, которого забудут через пять лет", ха, интересно, автор про себя писал?

"он не должен вмешиваться в прошлое"

Да, ёлки, уже его появление изменило ход событий! Если бы он не появился в прошлом, то младший он не сделал бы всего того что сделал, и не приехал бы к Илене с решением завести ребенка!

Илена погибла 30 лет назад, а Энжи 20 лет, значит это не дочь Илены (не считая вариантов заморозки яйцеклеток и суррогатного материнства)

Интересно, а Элиот понимает, что даже взмах крыла бабочки может лишить его дочери?

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

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

 Любая жизнь является ценной и значимой, и не важно кто это младенец, старик или собака. Да можно утрировать и напомнить про очень маленьких существ, которых давим не обращая на них внимания, поэтому здесь ремарка - в меру своих сил и возможностей. Герой - врач и бросает собаку, которой навредил, а его подруга ветеринар??? Да как они вообще вместе уже 10 лет?

 За 12000 тенге заменили масло и фильтр.

 Чую что эта пойдет не так просто

 Гийом Мюссо Ты будешь там

Поворот сюжета на столько неожидан, что предсказуем. Собственно сам поворот мне понравился, но в общем на один раз...

четверг, 1 декабря 2022 г.

Powershell script Список каталогов с полными доступом конкретному пользователю

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

Get-Acl -filter * -path * | where {(($_.access.IdentityReference -like "TSVR01\фрукты (все)") -or ($_.access.IdentityReference -like "TSVR01\sklad2")) -and ($_.access.FileSystemRights -like "FullControl") -and ($_.access.AccessControlType -like "Allow")} | ft -Property Path

Рекурсии нет, проверки всех групп также нет

Bash script аналог удаления файлов видеорегистратора

Удаление N старых файлов если объем занятого пространства на диске больше n

#!/bin/bash
# проверка наличия другого запущенного экземпляра
nameScript=$(basename "$0")
if [ "$(pgrep -c "$nameScript")" -gt 1 ]
then
	echo  "Script is run"
	exit
fi
# переменные, можно переделать в параметры
# каталог из которого удаляем файлы
directory=/home/tmk/testrm
# диск у которого проверяем объем
disk=/dev/sda
# глубина поиска файлов в каталоге (избавляемся от рекурсии)
depth=1
# количество файлов к удалению за один проход
amount=10
# лимит занятого простратнства (триггер)
MaxLimit="70"

# вариант IF EXIST, если перети не удалось, значит каталог или не существует или доступа туда нет, и выходим
cd "$directory" || exit
# Пока занятоно места больше $MaxLimit, удаляем старые данные в папке.
while [ "$(df -m | grep $disk | awk '{print $5}' | sed 's/%//g'))" -lt "$MaxLimit" ] 
do
# Если в каталоге, при необъходимой глубине, нет файлов, то на выход
	if [ "$(find "$directory" -type f -maxdepth $depth | head -n $amount)" != "" ]
	then
		# Ищем в той самой папке файлы, выводим с датой, сортируем по дате и удаляем первые в списке (самые старые) по $amount штук
        # т.к. перевод строки = \n, то использовать -0 для xargs не имеет смысла
		find "$directory" -maxdepth $depth -type f -printf "%T@ %p\n" | sort -n | cut -d" " -f2- | sed 's/ /\\ /g' | head -n $amount | xargs rm
	else
		echo "Free space is low, but directory is empty" 
		break
	fi
done


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

Самопроверка скрипта на наличие в процессах

#!/bin/bash
nameScript=$(basename "$0")
if [ "$(pgrep -c "$nameScript")" -gt 1 ]
then
	echo  "Script is run"
	exit
fi

Или (случайно нашел в интернетах 12/04/2024)

#!/bin/bash
instances=`lsof -t "$0" | wc -l`
if (( $instances > 1 )); then exit 1; fi

Вариант для mikrotik