Dynamic firewall blocklist
Posted: Mon Jul 17, 2023 5:01 am
Hi,
I'm trying to create a rudimentary firewall blocking rule using mikrotik scripting.
I'm not a huge fan of mikrotik scripting language, I am quite versed in a few other languages though.
Here's my situation: I'm getting regular gateway probes, which is common and usually not a problem. But I recently opened an IPSec tunnel on my gateway and since I started monitoring the logs to check the stabliity, I've been noticing a ton of attempted authentication attempts.
Now it is setup to best-practices standard and beyond. So by this time in readers are prob ready to start typing: "It's normal to get a few port scans, don't worry about it". or "Only allow certain subnets on the firewall rules".
In my scenario that isn't practical. I don't feel like typing all the reasons why it isn't a solution for me...just assume all the usual reasons are there like: I don't know from where my clients are gonna connect from etc.
Next best solution for me is to dynamically block attacking IP's for 24H or something. Best solution I could find there is to send the logs to a linux box and then do some logic and add the IP to a blocklist on the mikrotik via SSH or whatever. I have a few servers running that I can do this on but I feel this type of logic should be done on the mikrotik. If I wanted to route my traffic through a linux box I'd run a firewall server and not even let the mikrotik do the firewalling.
So I resorted to mikrotik scripting.
Here is a quick script I threw together (I took some inpiration from other code on the forum):
I was just hoping someone would go over my code to do some peer review and tell me if the code can be improved. Like I said I don't really have much mikrotik scripting experience.
Also can someone tell me how I would refine the /log find function to search for multiple log topics. For instance the firewall block rule log comes as [firewall, info], I'd like to refine the scripting so I can perfectly predict how the script will run.
And the /log find message~"negotiation failed" how do I specify that it should search for logs 'containing' or 'equals' etc
I'm trying to create a rudimentary firewall blocking rule using mikrotik scripting.
I'm not a huge fan of mikrotik scripting language, I am quite versed in a few other languages though.
Here's my situation: I'm getting regular gateway probes, which is common and usually not a problem. But I recently opened an IPSec tunnel on my gateway and since I started monitoring the logs to check the stabliity, I've been noticing a ton of attempted authentication attempts.
Now it is setup to best-practices standard and beyond. So by this time in readers are prob ready to start typing: "It's normal to get a few port scans, don't worry about it". or "Only allow certain subnets on the firewall rules".
In my scenario that isn't practical. I don't feel like typing all the reasons why it isn't a solution for me...just assume all the usual reasons are there like: I don't know from where my clients are gonna connect from etc.
Next best solution for me is to dynamically block attacking IP's for 24H or something. Best solution I could find there is to send the logs to a linux box and then do some logic and add the IP to a blocklist on the mikrotik via SSH or whatever. I have a few servers running that I can do this on but I feel this type of logic should be done on the mikrotik. If I wanted to route my traffic through a linux box I'd run a firewall server and not even let the mikrotik do the firewalling.
So I resorted to mikrotik scripting.
Here is a quick script I threw together (I took some inpiration from other code on the forum):
Code: Select all
# Created by: gh05t 2023 v0.1a
#
# This script adds ip of any address that hits a firewall block rule for 24hour
# Schedule the script to run every 5 min
#:log info message="RUNNING DYNAMIC FIREWALL BLOCK SCRIPT"
# Find all "negotiation failed" & "input" firewall errors for the last 5 mins
:local loglist [:toarray [/log find time>([/system clock get time] - 5m) (message~"input\$" || message~"negotiation failed\$")]]
# for all errors do
:foreach i in=$loglist do={
:local logMessage [/log get $i message]
:local ip [:pick $logMessage 0 [:find $logMessage " "]]
# Add ip to blocklist
/ip firewall address-list add address=$ip list=blocklist timeout=24h
# Send a message to the log
:log warning message="Dynamically adding $ip to firewall blocklist due to firewall deny hit or IPSec negotiation failed attempt"
}
Also can someone tell me how I would refine the /log find function to search for multiple log topics. For instance the firewall block rule log comes as [firewall, info], I'd like to refine the scripting so I can perfectly predict how the script will run.
And the /log find message~"negotiation failed" how do I specify that it should search for logs 'containing' or 'equals' etc