MANUAL: Mikrotik, colección de scripting

Gracias @diamuxin , aun estaba empezando con esto y efectivamente ya lo entendi. Tal como me pusiste funciona ok, creas un modulo y luego creas los scripts llamando a dicho modulo. Gracias de nuevo y por la explicacion
 
Como siempre, genial @pokoyo!

Os paso un script que conseguí hace tiempo (no recuerdo donde) que crea un reporte de IP's para posteriormente crear una regla en RAW que bloquee la citada lista, por si puede ser de utilidad:

Código:
delay 15
ip firewall address-list
:local update do={
:do {
:local data ([:tool fetch url=$url output=user as-value]->"data")
:local array [find dynamic list=blacklist]
:foreach value in=$array do={:set array (array,[get $value address])}
:while ([:len $data]!=0) do={
:if ([:pick $data 0 [:find $data "\n"]]~"^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}") do={
:local ip ([:pick $data 0 [:find $data $delimiter]].$cidr)
:do {add list=blacklist address=$ip comment=$description timeout=1d} on-error={
:do {set ($array->([:find $array $ip]-[:len $array]/2)) timeout=1d} on-error={}
}
}
:set data [:pick $data ([:find $data "\n"]+1) [:len $data]]
}
} on-error={:log warning "Address list <$description> update failed"}
}
$update url=http://feeds.dshield.org/block.txt description=DShield delimiter=("\t") cidr=/24
$update url=http://www.spamhaus.org/drop/drop.txt description="Spamhaus DROP" delimiter=("\_")
$update url=http://www.spamhaus.org/drop/edrop.txt description="Spamhaus EDROP" delimiter=("\_")
$update url=https://sslbl.abuse.ch/blacklist/sslipblacklist.txt description="Abuse.ch SSLBL" delimiter=("\r")
$update url=https://raw.githubusercontent.com/ktsaou/blocklist-ipsets/master/firehol_level2.netset description="FireHOL Level2" delimiter=("\n")
$update url=https://lists.blocklist.de/lists/all.txt description="BlockList.de" delimiter=("\n")

Saludos!
Este script está correcto? veo que saca la lista... pero no veo donde crea la regla raw...
 
Créala tú mismo con el nombre que le han dado en el script <blacklist>:

Código:
/ip firewall raw
add action=drop chain=prerouting src-address-list=blacklist

S@lu2.
Ahora sí, veo drop... menos de 2 minutos y ya tengo 10 entradas en los logs... :unsure:

UPDATE: 30min y 145 drops... ¿de verdad?
 
Última edición:
Ahora sí, veo drop... menos de 2 minutos y ya tengo 10 entradas en los logs... :unsure:

UPDATE: 30min y 145 drops... ¿de verdad?

No te alarmes, yo tengo una list-address con unas 30 ip´s que he ido cazando con intentos a los puertos 500-4500 (abiertos para ipsec) y ahora tengo 135 paquetes después de resetearse a las 12 de la noche.

Si has metido en el router todas las listas que lleva ese script es normal, son muchas IP´s. Además que afectará la RAM y CPU (depende del modelo que tengas).

S@lu2.
 
No te alarmes, yo tengo una list-address con unas 30 ip´s que he ido cazando con intentos a los puertos 500-4500 (abiertos para ipsec) y ahora tengo 135 paquetes después de resetearse a las 12 de la noche.

S@lu2.
Esos puertos los eliminé de mi FW hace tiempo, puesto que no uso IPSEC, recomiendo a quien no lo utilice que haga lo propio, ya que si no recuerdo mal es una regla que viene por defecto en el FW de Mikrotik.

Saludos!
 
Esos puertos los eliminé de mi FW hace tiempo, puesto que no uso IPSEC, recomiendo a quien no lo utilice que haga lo propio, ya que si no recuerdo mal es una regla que viene por defecto en el FW de Mikrotik.

Saludos!
Yo tengo una VPN tipo ipsec ikev2 con certificados como backup de wireguard, hace tiempo que no hay ningún "intento" de acceder a esos puertos.

S@lu2.
 
Necesito vuestra ayuda con la Integracion del viejo fail2ban con mikrotik... mi idea sería añadir la IP identificada por el fail2ban a una lista dinámica del mikrotik que ya estaria bloqueada con una regla previamente...

La tarea de añadir la IP a la lista ya la tengo funcionando, el problema está en la tarea de quitarla...

Añado IP detectada con:
actionban = mikrotik ":ip firewall address-list add address=<ip> list=fail2ban comment=fail2ban-<ip>"

Siendo el comentário bastante importante, pues lo tendré que usar para eliminar la IP en caso que necesite desbloquearla... la cosa es que no encuentro un comando para filtrar/buscar en una address list por determinado comentario... os suena algún modo de hacer esto?


La configuración está documentada aqui: https://wiki.mikrotik.com/wiki/Use_Mikrotik_as_Fail2ban_firewall
 
Necesito vuestra ayuda con la Integracion del viejo fail2ban con mikrotik... mi idea sería añadir la IP identificada por el fail2ban a una lista dinámica del mikrotik que ya estaria bloqueada con una regla previamente...

La tarea de añadir la IP a la lista ya la tengo funcionando, el problema está en la tarea de quitarla...

Añado IP detectada con:
actionban = mikrotik ":ip firewall address-list add address=<ip> list=fail2ban comment=fail2ban-<ip>"

Siendo el comentário bastante importante, pues lo tendré que usar para eliminar la IP en caso que necesite desbloquearla... la cosa es que no encuentro un comando para filtrar/buscar en una address list por determinado comentario... os suena algún modo de hacer esto?


La configuración está documentada aqui: https://wiki.mikrotik.com/wiki/Use_Mikrotik_as_Fail2ban_firewall

Aquí tienes estos bucles que te pueden ayudar a localizar IPs bloqueadas según los comentarios, declara variables locales y después ejecuta una acción.

Código:
# Lista cualquier IP que sea contenga "IPSec"
/ip firewall address-list
:foreach i in=[find where comment~"IPSec"] do={
  :local add [get $i address]
  :local tim [get $i creation-time]
  :put "$add \t $tim"
}

# Lista cualquier IP que sea distinto a "IPSec"
/ip firewall address-list
:foreach i in=[find where !(comment~"IPSec")] do={
  :local add [get $i address]
  :local tim [get $i creation-time]
  :put "$add \t $tim"
}

S@lu2.
 
Nada como revisar las cosas de nuevo por la mañana...

Es más sencillo de lo que pensaba...

/ip firewall address-list remove [find where comment="fail2ban-192.168.1.1"]

Gracias!
 
Última edición:
Nada como revisar las cosas de nuevo por la mañana...

Es más sencillo de lo que pensaba...

/ip firewall address-list remove [find where comment="fail2ban-192.168.1.1"]

Gracias!
Y, sin el “where”, también funciona.
Código:
Instrucción [find comment=“loquesea”] atributos

Saludos!
 
Una ultima pregunta... para que el user pueda hacer login por ssh y editar una lista tiene que estar en el grupo full como viene documentado en la wiki de mikrotik? no podria capar un poco ese user?
 
Una ultima pregunta... para que el user pueda hacer login por ssh y editar una lista tiene que estar en el grupo full como viene documentado en la wiki de mikrotik? no podria capar un poco ese user?
No. Puedes crear nuevos grupos con menos permisos. Con tener un grupo que tenga ssh + read + write, sospecho que te vale para que un usuario se pueda entrar por ssh, leer y modificar configuración del router.

Saludos!
 
Script muy útil para darnos información a diario (programarlo en scheduler) sobre el estado de nuestro sistema

Bash:
:local ipv4 [/ip cloud get public-address];
# :local ipv6 [/ip cloud get public-address-ipv6];   En RouterOS 6.49 no funciona esta línea
:local ipv6 [:pick [/ipv6 dhcp-client get [find] prefix] 0 24];
:local uptime [/system resource get uptime];
:local CurrentTemp [/system health get temperature];
:local FreeMemory ([/system resource get free-memory]/1000000);
:local TotalMemory ([/system resource get total-memory]/1000000);
:local cpu [/system resource get cpu];
:local cpuCount [/system resource get cpu-count];
:local cpuFrequency [/system resource get cpu-frequency];
:local cpuLoad [/system resource get cpu-load];
:local freeHdd ([/system resource get free-hdd-space]/1000000);
:local totalHdd ([/system resource get total-hdd-space]/1000000);
:local architectureName [/system resource get architecture-name];
:local boardName [/system resource get board-name];
:local version [/system resource get version];
:local DeviceName [/system identity get name];

# START Send Email Module
:local SendTo "micuenta@gmail.com";
:local Subject "\F0\9F\9A\80 $DeviceName System Status";
:local MessageText "IPv4: $ipv4\nIPv6: $ipv6\n\nTemperature: $CurrentTemp C\nUptime: $uptime\nFree Memory: $FreeMemory MB\nTotal Memory: $TotalMemory MB\nCPU: $cpu\nCPU Count: $cpuCount\nCPU Frequency: $cpuFrequency MHz\nCPU Load: $cpuLoad %\nFree Disk: $freeHdd MB\nTotal Disk: $totalHdd MB\nArchitecture: $architectureName\nBoard Name: $boardName\nSoftware Version: $version";
:local FileName "";
:local SendEmail [:parse [/system script get SendEmailFunction source]];
$SendEmail SendTo=$SendTo TextMail=$MessageText Subject=$Subject FileName=$FileName;
# END Send Email Module

# START Send Telegram Module
:local MessageText "\F0\9F\9A\80 $DeviceName System Status:%0AIPv4: $ipv4%0AIPv6: $ipv6%0ATemperature: $CurrentTemp %C2%B0 C%0AUptime: $uptime%0AFree Memory: $FreeMemory MB%0ATotal Memory: $TotalMemory MB%0ACPU Load: $cpuLoad %%0ACPU: $cpu%0ACPU Count: $cpuCount%0ACPU Frequency: $cpuFrequency MHz%0AArchitecture: $architectureName%0ABoard Name: $boardName%0ASoftware Version: $version%0AFree Disk: $freeHdd MB%0ATotal Disk: $totalHdd MB";
:local SendTelegramMessage [:parse [/system script  get MyTGBotSendMessage source]];
$SendTelegramMessage MessageText=$MessageText;
#END Send Telegram Module

:log info "Sent Email: WAN IP & System Status"
:log info "Sent Telegram: WAN IP & System Status"

Resultado por ejemplo en Telegram:

Ver el adjunto 84816

Editado 09/dic/2021: Script compatible con versión 7.1

Bash:
:local ipv4 [/ip cloud get public-address];
:local ipv6 [/ip cloud get public-address-ipv6];
:local uptime [/system resource get uptime];
:local CurrentTemp [/system health get [find name=temperature] value];
:local FreeMemory ([/system resource get free-memory] / 1024 / 1024);
:local TotalMemory ([/system resource get total-memory] / 1024 / 1024);
:local cpu [/system resource get cpu];
:local cpuCount [/system resource get cpu-count];
:local cpuFrequency [/system resource get cpu-frequency];
:local cpuLoad [/system resource get cpu-load];
:local freeHdd ([/system resource get free-hdd-space] / 1024 / 1024);
:local totalHdd ([/system resource get total-hdd-space] /1024 / 1024);
:local architectureName [/system resource get architecture-name];
:local boardName [/system resource get board-name];
:local version [/system resource get version];
:local DeviceName [/system identity get name];

# START Send Email
/tool e-mail send to="ginesidh@gmail.com" from="Mikrotik Despacho" subject="\F0\9F\9A\80 $DeviceName System Status" body="IPv4: $ipv4\nIPv6: $ipv6\n\nTemp: $CurrentTemp C\nUptime: $uptime\nFree Memory: $FreeMemory MB\nTotal Memory: $TotalMemory MB\nCPU: $cpu\nCPU Count: $cpuCount\nCPU Frequency: $cpuFrequency MHz\nCPU Load: $cpuLoad %\nFree Disk: $freeHdd MB\nTotal Disk: $totalHdd MB\nArchitecture: $architectureName\nBoard Name: $boardName\nSoftware Version: $version"
# END Send Email

# START Send Telegram Module
:local MessageText "\F0\9F\9A\80 $DeviceName System Status:%0AIPv4: $ipv4%0AIPv6: $ipv6%0ATemperature: $CurrentTemp %C2%B0 C%0AUptime: $uptime%0AFree Memory: $FreeMemory MB%0ATotal Memory: $TotalMemory MB%0ACPU Load: $cpuLoad %%0ACPU: $cpu%0ACPU Count: $cpuCount%0ACPU Frequency: $cpuFrequency MHz%0AArchitecture: $architectureName%0ABoard Name: $boardName%0ASoftware Version: $version%0AFree Disk: $freeHdd MB%0ATotal Disk: $totalHdd MB";
:local SendTelegramMessage [:parse [/system script  get MyTGBotSendMessage source]];
$SendTelegramMessage MessageText=$MessageText;
#END Send Telegram Module

:log info "Sent Email: WAN IP & System Status"
:log info "Sent Telegram: WAN IP & System Status"


Editado 03/feb/2022: Nuevas funcionalidades. Colaborador: @jerogabe

Se ha mejorado el script original añadiendo la obtención de información en cuanto a la cantidad de tráfico acumulado en la interfaz WAN (ether1, pppoe-out1, etc) tanto en TX, RX y Consumo total.

Para ello creamos un nuevo script que genera una variable Global y procuramos que este script se ejecute al arranque del router para que siempre esté disponible para su llamada por parte de cualquier script.

Este script o "función" se va a encargar de convertir a las distintas unidades B, KiB, MiB, GiB. dependiendo del valor obtenido "en bytes" al ejecutar la instrucción: [/interface get [find name=pppoe-out1] tx-byte]. En este caso tendríamos una respuesta por ejemplo de 849029897 pero a través de la nueva función lo convertiría a 812.2 MiB, esto ya es otra cosa...

Bien, creamos el script y lo ejecutamos:

Bash:
:global human do={
    :if ([:typeof $1]="nothing") do={
        :error "must provide a byte value to humanize";
    };
    :local input [:tonum $1];
    :if ([:typeof $input]!="num") do={
        :error "cannot convert $1 to number";
    };
    :local q;
    :local r;
    :local output;
    :if ($input<1024) do={
        :set $output "$input B";
    } else={
        :if ($input<1048576) do={
            :set q ($input/1024);
            :set r ($input-$q*1024);
            :set r ($r/102);
            :set output "$q.$r KiB";
        } else={
            :if ($input<1073741824) do={
                :set q ($input/1048576);
                :set r ($input-$q*1048576);
                :set r ($r/104858);
                :set output "$q.$r MiB"
            } else={
                :set q ($input/1073741824);
                :set r ($input-$q*1073741824);
                :set r ($r/107374182);
                :set output "$q.$r GiB"
            }
        }
    }
    :return $output
};

Como vemos, ha creado una variable global llamada "human" (la puedes llamar como quieras), ya estaría disponible para su uso. Lo puedes comprobar en Winbox en System -> Scripts -> Pestaña Environment.

Ahora el script modificado.

Bash:
# Llamada a la nueva variable global
:global human

:local ipv4 [/ip cloud get public-address];
:local ipv6 [/ip cloud get public-address-ipv6];
:local uptime [/system resource get uptime];
:local CurrentTemp [/system health get [find name=temperature] value];
:local FreeMemory ([/system resource get free-memory] / 1024 / 1024);
:local TotalMemory ([/system resource get total-memory] / 1024 / 1024);
:local cpu [/system resource get cpu];
:local cpuCount [/system resource get cpu-count];
:local cpuFrequency [/system resource get cpu-frequency];
:local cpuLoad [/system resource get cpu-load];
:local freeHdd ([/system resource get free-hdd-space] / 1024 / 1024);
:local totalHdd ([/system resource get total-hdd-space] /1024 / 1024);
:local architectureName [/system resource get architecture-name];
:local boardName [/system resource get board-name];
:local version [/system resource get version];
:local DeviceName [/system identity get name];
# nuevas variables
:local txtotal [$human [/interface get [find name=pppoe-out1] tx-byte]];
:local rxtotal [$human [/interface get [find name=pppoe-out1] rx-byte]];
:local sumtotal [$human ([/interface get pppoe-out1 tx-byte]+[/interface get pppoe-out1 rx-byte])];

# START Send Email
/tool e-mail send to="micuenta@gmail.com" from="Mikrotik Despacho" subject="\F0\9F\9A\80 $DeviceName System Status" body="IPv4: $ipv4\nIPv6: $ipv6\n\nTemp: $CurrentTemp C\nUptime: $uptime\nFree Memory: $FreeMemory MB\nTotal Memory: $TotalMemory MB\nCPU: $cpu\nCPU Count: $cpuCount\nCPU Frequency: $cpuFrequency MHz\nCPU Load: $cpuLoad %\nFree Disk: $freeHdd MB\nTotal Disk: $totalHdd MB\nArchitecture: $architectureName\nBoard Name: $boardName\nSoftware Version: $version\n\nConsumo total:\nDescarga: $rxtotal\nSubida: $txtotal\nTotal: $sumtotal"
# END Send Email

# START Send Telegram Module
:local MessageText "\F0\9F\9A\80 $DeviceName System Status:%0AIPv4: $ipv4%0AIPv6: $ipv6%0ATemperature: $CurrentTemp %C2%B0 C%0AUptime: $uptime%0AFree Memory: $FreeMemory MB%0ATotal Memory: $TotalMemory MB%0ACPU Load: $cpuLoad %%0ACPU: $cpu%0ACPU Count: $cpuCount%0ACPU Frequency: $cpuFrequency MHz%0AArchitecture: $architectureName%0ABoard Name: $boardName%0ASoftware Version: $version%0AFree Disk: $freeHdd MB%0ATotal Disk: $totalHdd MB%0A----%0A<b><i>Consumo total:</i></b>%0ADescarga: $rxtotal%0ASubida: $txtotal%0ATotal: $sumtotal";
:local SendTelegramMessage [:parse [/system script  get MyTGBotSendMessage source]];
$SendTelegramMessage MessageText=$MessageText;
#END Send Telegram Module

:log info "Sent Email: WAN IP & System Status"
:log info "Sent Telegram: WAN IP & System Status"

Así quedaría, como veis las unidades las ha traducido para su comprensión, como lo haría Winbox.

Ver el adjunto 91527 Ver el adjunto 91530

Gracias a @jerogabe por su aportación.

S@lu2.
Buenos días, tengo una duda con este script desde un RB4011 el caso es que no me muestra la frecuencia de la CPU y otros modelos de mikrotik si que me lo muestra como en el hAP ac2. ¿Es normal o es un fallo de mi router?

1671620650628.png
1671620754991.png


¿Os sale igual en un RB4011? Gracias
 
Última edición:
La línea implicada para obtener los datos de frecuencia de cpu es esta:

Código:
:local cpuFrequency [/system resource get cpu-frequency];

Puedes probarlo desde la terminal con este comando a ver que valor te da:

Código:
:put [/system resource get cpu-frequency]

Yo tengo un RB4011 con la última estable y no hay problema (bueno, estoy probando una beta):

1671623456470.png


Y mi script mañanero:

1671623708598.png


S@lu2.
 
Última edición:
La línea implicada para obtener los datos de frecuencia de cpu es esta:

Código:
:local cpuFrequency [/system resource get cpu-frequency];

Puedes probarlo desde la terminal con este comando a ver que valor te da:

Código:
:put [/system resource get cpu-frequency]

Yo tengo un RB4011 con la última estable y no hay problema (bueno, estoy probando una beta):

Ver el adjunto 102273

Y mi script mañanero:

Ver el adjunto 102276

S@lu2.
Gracias por responder, pero a mi no me saca la Frecuencia de CPU

1671626455426.png


Y el script lo tengo bien
1671626532588.png


¿ @diamuxin puede ser por que tú usas una versión superior a la mía? Ahora ya tengo la mosca detrás de la oreja.

EDITO:

1671627165048.png


Creo que es una cosa que se repara en la 7.7 beta 3, haber si me lo podéis confirmar. Gracias.
 
Última edición:
Gracias por responder, pero a mi no me saca la Frecuencia de CPU

Ver el adjunto 102279

Y el script lo tengo bien Ver el adjunto 102282

¿ @diamuxin puede ser por que tú usas una versión superior a la mía? Ahora ya tengo la mosca detrás de la oreja.

EDITO:

Ver el adjunto 102285

Creo que es una cosa que se repara en la 7.7 beta 3, haber si me lo podéis confirmar. Gracias.
Ahora que recuerdo, es un bug de las primeras versiones de 7.X y se lo tuve que anular en el script, si observas tu captura de winbox tampoco aparece la frecuencia de CPU.

Mikrotik ha implementado el ajuste automático de la frecuencia de CPU y se ve que en el RB4011 tuvieron algunos problemas que resolvieron en las últimas versiones.

1671628575300.png


No le des importancia, cuando actualices a la 7.7 estará resuelto.

Edito: yo lo tengo actualizado a una beta 7.7 por otros temas, no por esto.

S@lu2.
 
Uno de los problemas que he tenido usando la guía del router gorrón (y, que si no me equivoco, le pasa a bastante gente), es que Mikrotik se queda "empanado" y no conecta los túneles Wireguard una vez estos se han desconectado, especialmente en los casos en que se usan las DDNS como endpoints, siendo necesario desactivar y reactivar la interfaz o el túnel en si mismo desde "Pepe" para que este se levante y recupere la conexión.

Esto, al menos a mí, me resulta algo engorroso ya que requiere conectarse mediante Winbox o IP cada vez que esto ocurra, necesitando conectar físicamente. Como es un problema recurrente, me he puesto a buscar y he encontrado un script en los foros de Mikrotik que tal vez nos pueda ser útiles a los que tenemos el setup montado, o a cualquiera que tenga montado Wireguard y sufra este problema.

Lo que hace el script es comprobar si el túnel está activo, y en caso de que no lo esté, intenta, con espacios de 10s entre cada intento, reactivarlo, hasta un máximo de 15 intentos.

Evidentemente, todo el crédito al usuario que lo escribió (msatter). Dejo tanto el Script como el link abajo por si a alguien le puede servir:

Código:
{; # BeginOfScript

# scripted by msatter
# function: bring up stalled WireGuard interfaces after restart of the router

:local timesRetried   15;    # how many times WireGuard is tried to be restarted
:local loopDelay      "10s"; # (loopDelay * timesRetried ) = total timeout
:local restarted      true;  # set default to true
:local domainResolved false  # also checking if the endpoint domain-names could be resolved
:local retried        0;     # set to starting value

while ( $restarted  && ( $retried < $timesRetried ) )  do={ # loop till all Wireguard interfaces are working or there the maximum retries is reached
:set $restarted false
:foreach wg in=[/interface/wireguard/find disabled=no] do={
 :local peer [/interface/wireguard/get $wg name]
# scripted by Anav looking for domain names. Adapted by msatter. ( /in/ = /interface/ )
  :foreach i in=[/in/wireguard/peers/find interface=$peer endpoint-address~"[a-z]\$"] do={
   :if ([:resolve [/interface/wireguard/peers/get $i value-name=endpoint-address]]) do={ :set $domainResolved true
    :set $lastHandshake [/in/wireguard/peers/get $i last-handshake]
    :if (([:tostr $lastHandshake] = "") || ( $lastHandshake > [:totime [/in/wireguard/peers/get $i persistent-keepalive]])) do={
      /in/wireguard/ disable $peer; :delay 1s; /in/wireguard/ enable  $peer;    # restarting the WireGuard connection
      :set $restarted true
    }; # EndIf
   }; # EndIf
  }; # EndForeach
}; # EndForeach
:if (restarted) do={
 :put "Check loop: $retried"
 :set $retried ($retried + 1)
 :put "Checking loop: $retried"
 :delay $loopDelay; # waiting time till following check
}; #EndIf
}; # EndWhile
:if ( !$domainResolved ) do={:put "One or more domains could not be resolved, all/some domain based endpoints could not be brought up in the set time of ($timesRetried * $loopDelay)"} else={
 :if ( $restarted  && ( $retried > $timesRestied ) ) do={:put "Not all WireGuard interfaces could be brought up in the set time of ($timesRetried * $loopDelay)"}
 :if ( !$restarted && ( $retried > 0 ) ) do={:put "No WireGuard interfaces are down, after $retried retries"}
 :if ( $retried = 0 ) do={:put "No WireGuard interfaces had to be restared"}
}; # EndElse
}; #EndOfScript

Saludos!
 
Arriba