Firewall rule ordering - Ansible script for mikrotik management

Hi All,

I am using an ansible playbook which copies a configuration script to my mikrotiks and runs it each time we make a change. This allows us to keep configuration changes in version control and have automatic pushout of rules.

So far it seems to run ok however I am having an issue with firewall rules. The script checks if a rule already exists then adds it if it doesnt. After the rules are written, the script should put them in the right order. However the ordering doesnt work.

The code is:

##########################
# Apply the filter rules #
##########################
# We search based on comment here to minimise the number of finds we need to do and comments should be
# unique to each rule. It will not fail based on an IP address.
# Write rules in the order you want them to appear on the Mikrotik

# Allow establised and related input traffic
if ([:len [/ip firewall filter find where comment="SAWA - Accept Established / Related Input"]] = 0) \
 do={/ip firewall filter add chain=input comment="SAWA - Accept Established / Related Input" connection-state=established,related}

# Allow input from Ansible Server
if ([:len [/ip firewall filter find where comment="SAWA - Allow Input from Ansible"]] = 0) \
 do={/ip firewall filter add chain=input comment="SAWA - Allow Input from Ansible" src-address=x.x.x.x}

# Allow input from office
if ([:len [/ip firewall filter find where comment="SAWA - Allow Input from PH"]] = 0) \
 do={/ip firewall filter add chain=input comment="SAWA - Allow Input from PH" src-address=x.x.x.x}

# Drop Input
if ([:len [/ip firewall filter find where comment="SAWA - Drop all other Inputs"]] = 0) \
 do={/ip firewall filter add action=drop chain=input comment="SAWA - Drop all other Inputs" log=yes log-prefix="Input Drop"}

# Allow fasttracking of establised and related traffic
if ([:len [/ip firewall filter find where comment="SAWA - Fast Track Established / Related Forward"]] = 0) \
 do={/ip firewall filter add action=fasttrack-connection chain=forward comment="SAWA - Fast Track Established / Related Forward" connection-state=established,related}

# Allow forwarding of establised and related traffic
if ([:len [/ip firewall filter find where comment="SAWA - Accept Established / Related Forward"]] = 0) \
 do={/ip firewall filter add chain=forward comment="SAWA - Accept Established / Related Forward" connection-state=established,related}

# Allow Client LAN traffic out of the WAN
if ([:len [/ip firewall filter find where comment="SAWA - Allow client LAN traffic out WAN"]] = 0) \
 do={/ip firewall filter add chain=forward comment="SAWA - Allow client LAN traffic out WAN" out-interface=ether1 src-address=x.x.x.x/24}

# Drop Forward (currently disabled)
if ([:len [/ip firewall filter find where comment="SAWA - Drop All Forward"]] = 0) \
 do={/ip firewall filter add action=drop chain=forward comment="SAWA - Drop All Forward"}

# Ensure correct ordering of the firewall rules. Note the fast track dummy rule takes position 0
/ip firewall filter move [/ip firewall filter find comment="SAWA - Accept Established / Related Input"] destination=1
/ip firewall filter move [/ip firewall filter find comment="SAWA - Allow Input from Ansible"] destination=2
/ip firewall filter move [/ip firewall filter find comment="SAWA - Allow Input from PH"] destination=3
/ip firewall filter move [/ip firewall filter find comment="SAWA - Drop all other Inputs"] destination=4
/ip firewall filter move [/ip firewall filter find comment="SAWA - Fast Track Established / Related Forward"] destination=5
/ip firewall filter move [/ip firewall filter find comment="SAWA - Accept Established / Related Forward"] destination =6
/ip firewall filter move [/ip firewall filter find comment="SAWA - Allow client LAN traffic out WAN"] destination=7
/ip firewall filter move [/ip firewall filter find comment="SAWA - Drop All Forward"] destination=8

Running this just jumbles the rule order over and over again. Any ideas?

It may be better to do it this way:

  1. do an export of the rules to see if they already are what you want.
  2. if not: add a dummy rule with a unique comment, then the entire set of new rules in the correct sequence
  3. delete all rules up to and including the dummy rule matched by comment

That’s an interesting idea. I’m very new to Mikrotik scripting so not sure what that would look like code wise. Would be really grateful if you could suggest an example.

In the meantime I will see what I can figure out. Thank you for your suggestion.

Scripts can’t use numbers to target items. This is only from terminal.

You have two options (that is, if you don’t go with pe1chl’s approach):

  1. add a “place-before” argument to each rule added, and call “find” to find the rule before which the new one should be put.

e.g.

if ([:len [/ip firewall filter find where comment="SAWA - Accept Established / Related Input"]] = 0) \
 do={/ip firewall filter add chain=input comment="SAWA - Accept Established / Related Input" connection-state=established,related place-before=[/ip firewall filter find where comment="SAWA - Allow Input from Ansible"]}
  1. Remove the “destination” argument from “move”. When you do that, each “move” call will place the target item at the bottom of the list. Since you’re going through all items in order, by the end, they’ll be at the bottom of unmatched rules (if any), in that same order.


    BTW, with either option, you can save yourself some typing (and ultimately make things more readable) by placing the menu at the top. e.g.
/ip firewall filter

# Allow establised and related input traffic
if ([:len [find where comment="SAWA - Accept Established / Related Input"]] = 0) \
 do={add chain=input comment="SAWA - Accept Established / Related Input" connection-state=established,related}

# Allow input from Ansible Server
if ([:len [find where comment="SAWA - Allow Input from Ansible"]] = 0) \
 do={add chain=input comment="SAWA - Allow Input from Ansible" src-address=x.x.x.x}
 
 ##...
 
 # Ensure correct ordering of the firewall rules. Note the fast track dummy rule takes position 0
move [find comment="SAWA - Accept Established / Related Input"]
move [find comment="SAWA - Allow Input from Ansible"]

That looks like exactly what I am after. I really appreciate your input. Thank you.

I will do some testing this evening and let you know how I get on.

It worked brilliantly. Thank you.