Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Сетевое оборудование (http://forum.oszone.net/forumdisplay.php?f=55)
-   -   Mikrotik Router OS 7.17. Нужна помощь в написании скрипта. (http://forum.oszone.net/showthread.php?t=356132)

barozzzy 14-02-2025 14:19 3035993

Mikrotik Router OS 7.17. Нужна помощь в написании скрипта.
 
Доброго времени суток.
Есть такая задача:
Имеется Mikrotik на базе Router OS 7.17, нужен скрипт, который будет проверять не лог на предмет не верной авторизации (api, Winbox, ssh), брать ip адрес и добавлять его в Adress List.

Используя ИИ (ChatGPT и DeepSeek) пробовал сгенерировать код (не силен в написании кодов), при каждом варианте лог сообщал
Лог ошибки
executing script blockbruteforce from winbox failed, please check it manually


А вот сами варианты скрипта:
ChatGPT_1
/system logging action add name=bruteforce target=memory
/system logging add topics=login action=bruteforce

:global blocklist "bruteforceblock"
/ip firewall address-list add list=$blocklist address=0.0.0.0 comment="Temporary list for brute-force attackers"

:local maxAttempts 5
:local banTime 1d

:while (true) do={
:local logEntries [/log find where topics~"login failure"]

:foreach entry in=$logEntries do={
:local message [/log get $entry message]
:if ([:find $message "via ssh" -1] != -1 || [:find $message "via winbox" -1] != -1 || [:find $message "via api" -1] != -1) do={
:local ip [:pick $message ([:find $message "from "]+5) [:find $message " via"]]

:local count [/ip firewall address-list find where list=$blocklist && address=$ip]
:if ([:len $count] = 0) do={
/ip firewall address-list add list=$blocklist address=$ip timeout=$banTime comment="Blocked due to brute-force"
:log warning "Blocked IP $ip due to multiple failed SSH/Winbox/API login attempts."
}
}
}
:delay 10s
}


ChatGPT_2
/system logging action add name=bruteforce target=memory
/system logging add topics=login action=bruteforce

:global blocklist "bruteforceblock"
:local maxAttempts 5
:local banTime "1d"

:while (true) do={
:local logEntries [/log find where topics~"critical"]

:foreach entry in=$logEntries do={
:local message [/log get $entry message]
:log info "Checking message: $message"

:if ([:find $message "via ssh" -1] != -1 || [:find $message "via winbox" -1] != -1 || [:find $message "via api" -1] != -1) do={
:local ipStart ([:find $message "from "] + 5)
:local ipEnd [:find $message " via"]
:if ($ipEnd > 0) do={
:local ip [:pick $message $ipStart $ipEnd]
:log info "Extracted IP: $ip"

:local count [/ip firewall address-list find where list=$blocklist && address=$ip]
:if ([:len $count] = 0) do={
/ip firewall address-list add list=$blocklist address=$ip timeout=$banTime comment="Blocked due to brute-force"
:log warning "Blocked IP $ip due to multiple failed login attempts."
}
} else={
:log error "Failed to extract IP from message: $message"
}
}
}
:delay 10s
}


DeepSeek_1
{
:local blocklist "bruteforceblock" # Название списка блокировки
:local maxAttempts 5 # Максимальное количество попыток
:local banTime "1d" # Время блокировки
:local failedIPs [:toarray {}] # Массив для хранения количества попыток

:local logEntries [/log find where topics~"critical"]

:foreach entry in=$logEntries do={
:local message [/log get $entry message]
:log info "Checking message: $message"

# Проверяем, связано ли сообщение с неудачной попыткой входа
:if ([:find $message "login failure for user"] != nil) do={
:local ipStart ([:find $message "from "] + 5)
:local ipEnd [:find $message " via"]
:local ip [:pick $message $ipStart $ipEnd]

:if ($ip != "") do={
:log info "Extracted IP: $ip"
:local ipCount 1

# Проверяем, есть ли уже запись об этом IP в массиве
:foreach ipEntry in=$failedIPs do={
:if ([:pick $ipEntry 0 [:find $ipEntry "="]] = $ip) do={
:set ipCount ([:pick $ipEntry ([:find $ipEntry "="] + 1) [:len $ipEntry]] + 1)
:set $failedIPs [:tostr [:replace $failedIPs $ipEntry ($ip . "=" . $ipCount)]]
}
}

# Если IP не найден в массиве, добавляем его
:if ($ipCount = 1) do={
:set $failedIPs [:tostr [:merge $failedIPs [:toarray [$ip . "=" . $ipCount]]]
}

# Если попыток больше maxAttempts, блокируем IP
:if ($ipCount >= $maxAttempts) do={
/ip firewall address-list add list=$blocklist address=$ip timeout=$banTime comment="Blocked due to brute-force"
:log warning "Blocked IP $ip due to $ipCount failed login attempts."
}
} else={
:log error "Failed to extract IP from message: $message"
}
}
}
}


DeepSeek_2
/system script add name=block_bruteforce source="
:local blockTime 1d # Время блокировки (например, 1 день)
:local maxAttempts 3 # Количество неудачных попыток до блокировки
:local addressList \"BruteForce_Block\" # Название списка блокировки

:local failedIPs [:toarray {}] # Используем массив для хранения данных

:foreach logEntry in=[/log find where topics~\"account,info\"] do={
:local logMsg [/log get \$logEntry message]

# Проверяем, есть ли в сообщении 'login failure'
:if ([:find \$logMsg \"login failure for user\"] != nil) do={
:local startIndex [:find \$logMsg \"from\"]
:local failedIP [:pick \$logMsg (\$startIndex + 5) [:len \$logMsg]]

# Проверяем, не в списке ли уже этот IP
:if ([:len [/ip firewall address-list find where address=\$failedIP]] = 0) do={
:local ipCount 1

# Проверяем, есть ли уже запись об этом IP в массиве
:foreach ipEntry in=\$failedIPs do={
:if ([:pick \$ipEntry 0 [:find \$ipEntry \"=\"]] = \$failedIP) do={
:set ipCount ([:pick \$ipEntry ([:find \$ipEntry \"=\"] + 1) [:len \$ipEntry]] + 1)
:set \$failedIPs [:tostr [:replace \$failedIPs \$ipEntry (\$failedIP . \"=\" . \$ipCount)]]
}
}

# Если IP не найден в массиве, добавляем его
:if (\$ipCount = 1) do={
:set \$failedIPs [:tostr [:merge \$failedIPs [:toarray [\$failedIP . \"=\" . \$ipCount]]]]
}

# Если попыток больше maxAttempts, блокируем IP
:if (\$ipCount >= \$maxAttempts) do={
/ip firewall address-list add list=\$addressList address=\$failedIP timeout=\$blockTime
:log warning \"Blocked IP \$failedIP after \$ipCount failed login attempts!\"
}
}
}
}"


Вариантов было намного больше, но я выложил крайние.

Может кто нибудь поможет в данном вопросе?

Anton04 15-02-2025 10:33 3036003

Цитата:

Цитата barozzzy
нужен скрипт, который будет проверять не лог на предмет не верной авторизации (api, Winbox, ssh), брать ip адрес и добавлять его в Adress List. »

Зачем так делать? Не лучше ли банально НЕ выставлять порты api, Winbox, ssh голой попой наружу, чтоб к Вам все стучались!?
Закройте порты в наружи и подключайтесь к микроту по VPN или используйте port knocking и не занимайтесь бесполезной фигнёй.

P.S. Буквально два правила port knocking решат Вашу проблему:

Код:

/ip firewall filter
add action=add-src-to-address-list address-list=allow-ip \
    address-list-timeout=1h chain=input comment="icmp allow-ip list" \
    in-interface-list=WAN-list packet-size=123 protocol=icmp
add action=accept chain=input comment="Winbox and SSH" dst-port=22,8291 \
    in-interface-list=WAN-list protocol=tcp src-address-list=allow-ip


bredych 16-02-2025 03:13 3036010

а можно пояснить строки?
как понял, по какому-то листу разрешен вход, но где этот лист и почему срок разрешения час?
или имелось в виду блокирование, а не разрешение?

Cereal Keeler 16-02-2025 11:52 3036011

Цитата:

Цитата bredych
а можно пояснить строки? »

Первое правило добавляет src ip, с которого приходит пинг размером 123 байта на интерфейсы в списке WAN-list в список под названием allow-ip на 1 час. Через 1 час этот адрес оттуда удаляется.
Второе правило разрешает доступ по портам 22,8291 на интерфейсы в списке WAN-list для адресов, находящихся в списке allow-ip.
Предполагается, что доступ по умолчанию запрещён.

Стоило также написать, что стучать в калитку в данном случае следует так:
Код:

ping <mikrotik-ip-in-WAN-list> -l 95 -n 1
95+28=123
28 - размер заголовка.
Цитата:

Цитата bredych
почему срок разрешения час? »

Так в приведённом примере. Никто не запрещает открывать калитку хоть на сутки, или вообще навсегда. Или, с другой стороны, на 30-60 секунд, чтоб пройти самому, а соседи на мобильном интеренете, коих десятки тысяч, не проскочили. Как настроишь, так и будет.
Методы стука тоже есть разные, Anton04 привёл самый простой для исполнения со стороны клиента - ping практически везде есть, а скажем nmap - не везде.

bredych 17-02-2025 10:05 3036023

Цитата:

Цитата Cereal Keeler
Или, с другой стороны, на 30-60 секунд, чтоб пройти самому, а соседи на мобильном интеренете, коих десятки тысяч, не проскочили »

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

Anton04 17-02-2025 11:36 3036024

Цитата:

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

Коротко:

1. Нет.
2. Подключился и работай.
3. ping -n 2 -l 95 "IP или адрес узла".

Развёрнуто:

1. Все зависит от того какие услуги Вам предоставляет Ваш провайдер, если не выдаёт "белые" IP, то в микроте зафиксируется IP конечного шлюза, если выдаёт белый статический IP адрес, то в микроте появится именно этот адрес.
2. Послали ICMP пакет определённой длинный, микрот принял пакет обработал и добавил адрес источника от куда он пришёл в белый список. далее вы подключаетесь в течении указанного в правиле времени и работаете, можете не закрывать Windows или ssh хоть сутками, т.к. время важно только для новых подключений.
3. Смотря что вы подразумеваете под "сессией", в сетях есть такое понятие время жизни соединения, т.е. время в течении которого соединение считается активным (т.е. рабочим). Если вы подразумеваете это, то если активна сессия, то запрос на открытие параллельной сессии считается нормальным. За это у Вас должно отвечать другое правило в самом верху, пример:

Код:

/ip firewall filter
add action=accept chain=input comment=\
    "accept input established,related" connection-state=\
    established,related


Cereal Keeler 17-02-2025 13:02 3036025

Цитата:

Цитата bredych
пардон, а у всех с мобильного инета будет один ип? »

Не у всех, но стопудово у очень многих, если опсос использует NAT/CGNAT, что обычно и наблюдаю, хотя может какие-то и выдают публичные адреса, но чёт сомневаюсь, при нынешнем их дефиците это расточительно. Для опсосов даже специальную CGNAT подсеть выделили: 100.64.0.0/10, то есть, в теории за одним публичным ip может сидеть до 4+ млн клиентов. На практике их конечно меньше, но тысячи и десятки тысяч - запросто. Могут и классический NAT по RFC 1918 использовать, мой опсос например использует 10.0.0.0/8, на 16+ млн адресов, хоть столько клиентов у него и близко нет.

Cereal Keeler 18-02-2025 16:40 3036075

Цитата:

Цитата Anton04
если выдаёт белый статический IP адрес, то в микроте появится именно этот адрес. »

Но тогда и в калитку стучать незачем, завайтлистил руками этот адрес навсегда и всё. Port knocking это ж для тех случаев, когда админу нужно срочно получить доступ из небезопасной помойки – мобильная сеть, публичный вайфай и тп. И у него почему-то нет VPN - то ли не умеет, то ли денег страшно жалко – аж десятку евро в месяц на VPS c ним. Супербомжовое и совсем небезопасное решение, но, да, лучше, чем держать голую жопу выставленной в публичный доступ, даже если проверять её на проникновения, как хотел OP.

Anton04 18-02-2025 18:43 3036077

Цитата:

Цитата Cereal Keeler
Но тогда и в калитку стучать незачем, завайтлистил руками этот адрес навсегда и всё. »

Это хоть в какой-то мере убережёт от подмены IP или по крайней мере затруднит. Но да, лучше уж VPN настроить на самом микроте.

Cereal Keeler 18-02-2025 18:55 3036078

Цитата:

Цитата Anton04
Это хоть в какой-то мере убережёт от подмены IP »

От ip spoofing? Ребята, если за вас взялись на таком уровне, то калитка уже не поможет.


Время: 21:29.

Время: 21:29.
© OSzone.net 2001-