Community discussions

 
ghusson
just joined
Topic Author
Posts: 5
Joined: Thu Mar 01, 2018 11:41 am

Staging script example

Fri Mar 16, 2018 3:57 pm

Hello, I began a script for staging automation in 2017.
I have put my hand in it today in order to generate suitable VLAN configurations after the December 2017 update of RouterOS.
Currently it is working on CRS112 in "switch" mode. And at last I wanted to share it in its current state.
It shows some interesting things that we can do with Mikrotik LUA scripting.
I won't spent much time in order to support/maintain it, thus feel free to take it, improve it, reshare it (could be a great project for Mikrotik community !) - or to pay me for developments :-p

BR
Gautier from Liberasys.

# ====== Initial Mikrotik configuration template ======
# By Gautier HUSSON - HUSSON CONSULTING SAS - Liberasys (Britany, FRANCE)
# contact_web@liberasys.com - www.liberasys.com
# Revision : 0.4 / 20180316
# Status : not much tested, please prepare your serial console or USB/WIFI dongle !

#TODO : ethernet : configure loop protection (check if bug correction is OK)
#TODO : check vlan names between differents arrays
#TODO : verify we have at last one port associated to admin vlan
#TODO : firewall : implement DNS resolution in access-lists
#TODO : firewall : optimisation for : established/related sooner, add some connection state = new
#TODO : firewall : add a generic function that create rules for brute force mitigation over TCP and input a list of ports (ex : 3389)
#TODO : Certificates : generates new ones only if olders are bad
#TODO : check that master port is defined in vlansConfig
#TODO : check functionnalModeConfig // switch mode and VLAN unaware chip
#TODO : bridges : add DHCP server/client configuration an apply it
#TODO : look at HTTPs protection, maybe disallow it from all

# Disclaimer of Warranty.
#  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
# APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
# HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
# OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
# IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
# ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

# Limitation of Liability.
#  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
# WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
# THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
# GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
# USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
# DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
# PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
# EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGES.

# ======================================================================
# TIPS with scripts (or /import for syntax check) - thanks to Martin S. from Mikrotik :-) :
# ======================================================================
# Create and edit system script with CLI :
# Remark : you can otherwise import them from file.
#   /system script remove staging
#   /system script add name=staging
#   /system script edit staging source
#   paste your script
#   Ctrl+o
# Review your syntax :
#   /system script edit staging source
#   other solution :
#   /system script print where name=staging
# Run your script :
#   /system script run staging

# ======================================================================
# = Advices
# ======================================================================
# 1) change parameters here under in "Input variables" paragraph
# 2) either :
#    - start from blank configuration (use serial terminal):
#      /system reset-configuration no-defaults=yes
#      with serial line, pass lines with copy/paste
#      do it by paragraphs or serial line will give errors - buffer ov maybe
#      (sudo screen /dev/ttyUSB0 115200)
#    - upload the file (.rsc) on your mikrotik
#      CLI : /system reset-configuration no-defaults=yes run-after-reset=<my_filename.rsc>
#    - apply with /import or script run, at your risk (can cut legs !)



:put ""
:put "========================================================================"
:put "=== Setting environment global variables"
:put "========================================================================"

# Remark : everywhere there is an IP, you can put nothing ("") and the configurations using
#          the IP will be bypassed. Everywhere but authorizedAdminNetwork ! :-)

# functionnalModeConfig defines the mode of configuration
# 3 possible values :
#  - "switch" : the adminVlanNameConfig only will have an IP, and no routing will be configured
#  - "router" : all the VLANs will be forwarded and the OS will do routing
#  - "firewall" : all the VLANs will be forwarded and the routing will be firewalled
:global functionnalModeConfig "switch"

# /!\  !!! CHANGE ME !!!!  /!\ :
:global adminUserName "miktikadm"
:global adminPassword "miktikadm31337"
# /!\  !!! CHANGE ME !!!!  /!\ :

# vlan names definition (will be used in bridge names and vlan interfaces too)
:global vlanNamesConfig {
                        "liberasys_lan"="250";
                        "liberasys_dmz"="210";
                        "liberasys_dmz_tiers"="220";
                        "liberasys_invite"="205";
                        "liberasys_lab"="207";
                        "creafab_lan"="5";
                        "internet_uplink"="200";
                        }
:global adminVlanNameConfig "liberasys_lan"
:global internetVlanNameConfig "internet_uplink"


# Ips on bridges :
:global bridgesIps {
                   "liberasys_lan"="192.168.250.80/24";
                   }

# vlan definition per interface
# special data structure in order do describe wanted configuration
# for vlans array, the special value "all" is replaced by each vlan
:global vlansConfig {
                    ether1={mode="untagged"; vlans={"liberasys_lan";};};
                    ether2={mode="untagged"; vlans={"liberasys_lan";};};
                    ether3={mode="untagged"; vlans={"liberasys_lan";};};
                    ether4={mode="untagged"; vlans={"liberasys_lan";};};
                    ether5={mode="untagged"; vlans={"liberasys_dmz";};};
                    ether6={mode="untagged"; vlans={"liberasys_dmz";};};
                    ether7={mode="untagged"; vlans={"liberasys_dmz_tiers";};};
                    ether8={mode="untagged"; vlans={"liberasys_dmz_tiers";};};
#                    ether9={mode="untagged"; vlans={"data";};};
#                    ether10={mode="untagged"; vlans={"services";};};
#                    ether11={mode="untagged"; vlans={"services";};};
#                    ether12={mode="untagged"; vlans={"services";};};
#                    ether13={mode="untagged"; vlans={"services";};};
#                    ether14={mode="untagged"; vlans={"services";};};
#                    ether15={mode="untagged"; vlans={"services";};};
#                    ether16={mode="untagged"; vlans={"services";};};
#                    ether17={mode="untagged"; vlans={"services";};};
#                    ether18={mode="untagged"; vlans={"services";};};
#                    ether19={mode="untagged"; vlans={"services";};};
#                    ether20={mode="untagged"; vlans={"services";};};
#                    ether21={mode="trunk"; vlans={"admin"; "data"; "services"};};
#                    ether22={mode="tagged";vlans={"internet"};};
#                    ether23={mode="untagged"; vlans={"internet";};};
#                    ether24={mode="trunk"; vlans={"all";};};
#                    sfp1={mode="trunk"; vlans={"all";};};
#                    sfp2={mode="trunk"; vlans={"all";};};
#                    sfp3={mode="trunk"; vlans={"all";};};
#                    sfp4={mode="trunk"; vlans={"all";};};
                    sfp9={mode="trunk"; vlans={"all";};};
                    sfp10={mode="trunk"; vlans={"all";};};
                    sfp11={mode="trunk"; vlans={"all";};};
                    sfp12={mode="trunk"; vlans={"all";};};
                    }


:global localFqdn "plmasw01.liberasys.com";
:global timeZone "Europe/Paris"
:global authorizedAdminNetwork "192.168.0.0/16"
:global defaultGw "192.168.250.254"
:global dnsServers "192.168.250.254,192.168.200.254"
:global ntpServerIp1 "37.187.56.220"
:global ntpServerIp2 "5.135.3.88"
:global ntpServersFqdns "0.fr.pool.ntp.org,1.fr.pool.ntp.org,2.fr.pool.ntp.org,3.fr.pool.ntp.org"
:global syslogServerIp "192.168.210.10"

# verboseConfig : "yes" or "no"
:global verboseConfig "yes"

# DON'T TOUCH THOSE VARIABLES :
:global configurationOk "true"



# ======================================================================
# = Copyright and SOS beeps
# ======================================================================

# Initial delay, if system is booting, it is mandatory
#:delay 20s;

:put "====== Initial Mikrotik configuration template ======"
:put "By Gautier HUSSON - HUSSON CONSULTING SAS - Liberasys"
:put "License : CC BY 4.0"
:put "          https://creativecommons.org/licenses/by/4.0/"
:put ""
:put "WARNING WARNING WARNING WARNING WARNING WARNING"
:put "WARNING WARNING WARNING WARNING WARNING WARNING"
:put "WARNING WARNING WARNING WARNING WARNING WARNING"
:put ""
:put "You will loose almost all your configuration."
:put "You have 5 seconds to quit (Ctrl + C)."
:put ""
:delay 0.2s
:beep length=0.1s
:delay 0.2s
:beep length=0.1s
:delay 0.2s
:beep length=0.1s

:delay 0.5s
:beep length=0.3s
:delay 0.5s
:beep length=0.3s
:delay 0.5s
:beep length=0.3s
:delay 0.5s

:beep length=0.1s
:delay 0.2s
:beep length=0.1s
:delay 0.2s
:beep length=0.1s
:delay 0.5s



:put ""
:put "========================================================================"
:put "=== Defining internal functions"
:put "========================================================================"

# keyInSimpleArray: returns true or false
# arg1: key name
# arg2: array (without values attached to keys)
# use example: :put [$keyInArray "plop" $localEthernetInterfaces]
:global keyInSimpleArray do={
  :local arraySize [:len $2]
  :if ( $arraySize = 0) do={ :return "false"; };
  :foreach key in=$2 do={
    :if ($1 = $key) do={ :return "true"; };
    }
  :return "false";
  }

# keyInArray: returns true or false
# arg1: key name
# arg2: array (with values attached to keys)
# use example: :put [$keyInArray "plop" $localEthernetInterfaces]
:global keyInArray do={
  :local arraySize [:len $2]
  :if ( $arraySize = 0) do={ :return "false"; };
  :foreach key,value in=$2 do={
    :if ($1 = $key) do={ :return "true"; };
    }
  :return "false";
  }



:put ""
:put "========================================================================"
:put "=== Generating some variables"
:put "========================================================================"

# Compute administration IP
:global administrationIp
:set administrationIp
:global administrationIp
:set administrationIp [:pick ($bridgesIps->$adminVlanNameConfig) 0 [:find ($bridgesIps->$adminVlanNameConfig) "/"]]


# Compute Internet bridge name
:global internetBridgeNameConfig
:set internetBridgeNameConfig
:global internetBridgeNameConfig
:set internetBridgeNameConfig ("br-".$internetVlanNameConfig."-v".($vlanNamesConfig->$internetVlanNameConfig))


# Compute hostname
:global localHostname;
:set localHostname;
:global localHostname;
:set localHostname [:pick ($localFqdn) 0 [:find ($localFqdn) "."]];


# Replace vlan "all" by each vlan in vlansConfig
:global vlanNameArray
:set vlanNameArray
:global vlanNameArray
:foreach vlanName,vlanId in=$vlanNamesConfig do={
  :set vlanNameArray ($vlanNameArray, $vlanName)
  }
:foreach iface,conf in=$vlansConfig do={
  :foreach vlan in=($conf->"vlans") do={
    :if (vlan = "all") do={
      :set ($conf->"vlans") $vlanNameArray
      }
    }
  }


# Create table of all ethernet interfaces
:global localEthernetInterfaces
:set localEthernetInterfaces
:global localEthernetInterfaces
:foreach ifaceIndex in=[/interface find where type="ether"] do={
  #:put [/interface ethernet get value-name=default-name number=$ifaceIndex]
  :set localEthernetInterfaces ($localEthernetInterfaces, [/interface ethernet get value-name=default-name number=$ifaceIndex])
  }
#:put [:tostr $localEthernetInterfaces]
#:environment print


# Create array for EGRESS ports TO TAG : vlan -> interfaces list
:global egressPortsToTagArray
:set egressPortsToTagArray
:global egressPortsToTagArray ([:toarray ""])
:foreach iface,conf in=$vlansConfig do={
  :if ($conf->"mode" = "tagged" or $conf->"mode" = "trunk") do={
    :foreach vlan in=($conf->"vlans") do={
      #:put ($iface.":".($conf->"mode")." : ".$vlan)
      :set ($egressPortsToTagArray->($vlanNamesConfig->$vlan))  (($egressPortsToTagArray->($vlanNamesConfig->$vlan)).$iface.",")
      }
    }
  }
# translate sub arrays in form of values to arrays
:foreach vlanId,ifaces in=$egressPortsToTagArray do={
  :set ($egressPortsToTagArray->$vlanId)  ([:toarray ($egressPortsToTagArray->$vlanId)])
  }


# Create array for INGRESS ports TO TAG : vlan -> interfaces list (same begin as egressPortsToTagArray, with only untagged ports)
:global ingressPortsToTagArray;
:set $ingressPortsToTagArray;
:global ingressPortsToTagArray ([:toarray ""]);
:foreach iface,conf in=$vlansConfig do={
  :if ($conf->"mode" = "untagged") do={
    :foreach vlan in=($conf->"vlans") do={
      :set ($ingressPortsToTagArray->($vlanNamesConfig->$vlan))  (($ingressPortsToTagArray->($vlanNamesConfig->$vlan)).$iface.",")
      }
    }
  }
  # translate sub arrays in form of values to arrays
  :foreach vlanId,ifaces in=$ingressPortsToTagArray do={
    :set ($ingressPortsToTagArray->$vlanId)  ([:toarray ($ingressPortsToTagArray->$vlanId)])
    }



:put ""
:put "========================================================================"
:put "=== Checking input variables"
:put "========================================================================"

# Print the VLANS definitions
:if ($verboseConfig = "yes") do={
  :put "===  vlansConfig :"
  :foreach key,value in=$vlansConfig do={
    :put ($key." (".([:tostr ($value->"mode")]).")")
    :foreach key2 in=($value->"vlans") do={
      :put ("  ".([:tostr ($key2)]))
      }
    }
  }

# Print the interfaces per vlan table
:if ($verboseConfig = "yes") do={
  :put "===  egressPortsToTagArray :"
  :foreach vlanId,ifaces in=$egressPortsToTagArray do={
    :put ("Vlan : ".$vlanId)
    :foreach iface in=$ifaces do={
      :put ("  ".$iface)
      }
    }
  }

# Check that the authorizedAdminNetwork IP is filled
:if ($configurationOk = "true") do={
  :if ([:len $authorizedAdminNetwork] < 7) do={
    :put ("!!!!!!!! Invalid IP for $authorizedAdminNetwork, your equipment will be unmanageable")
    :beep frequency=220 length=2s
    :set configurationOk "false"
    }
  }

# Check bridges IPs : there should be at last one IP in the administration VLAN
:if ($configurationOk = "true") do={
  :if ([:len ($bridgesIps->$adminVlanNameConfig)] < 1) do={
    :put ("!!!!!!!! No IP configured on admin bridge, your equipment will be unmanageable")
    :beep frequency=220 length=2s
    :set configurationOk "false"
    }
  }

# Check bridges IPs : in switch mode, only the admin bridge should have an IP
:if ($configurationOk = "true") do={
  :if ($functionnalModeConfig = "switch") do={
    :if ([:len $bridgesIps] != 1) do={
      :put ("!!!!!!!! Too many IPs configured on bridges")
      :beep frequency=220 length=2s
      :set configurationOk "false"
      }
    }
  }

# Check vlansConfig array : interface names
:if ($configurationOk = "true") do={
  :foreach key,value in=$vlansConfig do={
    :if (!([$keyInSimpleArray $key $localEthernetInterfaces] = "true")) do={
      :put ("!!!!!!!! Invalid interface found: ".$key)
      :beep frequency=220 length=2s
      :set configurationOk "false"
      }
    }
  }

# Check vlansConfig array : mode
:if ($configurationOk = "true") do={
  :foreach key,value in=$vlansConfig do={
    :if ($value->"mode" != "untagged" and $value->"mode" != "tagged" and $value->"mode" != "trunk") do={
      :put ("!!!!!!!! Invalid mode found: \"".$value->"mode"."\" for \"".$key."\" interface")
      :beep frequency=220 length=2s
      :set configurationOk "false"
      }
    }
  }

# Check vlansConfig array : vlans number
:if ($configurationOk = "true") do={
  :foreach key,value in=$vlansConfig do={
    :local vlanNumber ([:len ($value->"vlans")])
    #:put ("vlan number for ".$key." : ".$vlanNumber)
    :if ($value->"mode" = "untagged" or $value->"mode" = "tagged") do={
      :if ([:len ($value->"vlans")] != 1) do={
        :put ("!!!!!!!! Invalid vlan numbers found for ".$key." (".$vlanNumber." vlans for ".($value->"mode")." mode : ".[:tostr ($value->"vlans")]." )")
        :beep frequency=220 length=2s
        :set configurationOk "false"
        }
      }
    :if ($value->"mode" = "trunk") do={
      :if ([:len ($value->"vlans")] < 1) do={
        :put ("!!!!!!!! Invalid vlan numbers found for ".$key." (".$vlanNumber." vlans for ".($value->"mode")." mode )")
        :beep frequency=220 length=2s
        :set configurationOk "false"
        }
      }
    }
  }

# Check vlansConfig array : vlans names
:if ($configurationOk = "true") do={
  :foreach key,value in=$vlansConfig do={
    :foreach key2 in=($value->"vlans") do={
      #:put ($key." ".$key2)
      :if (!([$keyInArray $key2 $vlanNamesConfig] = "true")) do={
        :put ("!!!!!!!! Invalid vlan name found : ".$key2." for ".$key)
        :beep frequency=220 length=2s
        :set configurationOk "false"
        }
      }
    }
  }

# Check functionnalModeConfig value
:if ($configurationOk = "true") do={
  :if ($functionnalModeConfig != "switch" and $functionnalModeConfig != "router" and $functionnalModeConfig != "firewall") do={
    :put ("!!!!!!!! Invalid functionnal name found : ".$functionnalModeConfig.". Possible values : switch, service, firewall")
    :beep frequency=220 length=2s
    :set configurationOk "false"
    }
  }

# Get out if configuration is bad
:if ($configurationOk = "false") do={
  :return "Bad configuration detected, abording !"
  }



:put ""
:put "========================================================================"
:put "=== Removing existing conflictual configuration - for idempotency"
:put "========================================================================"

# Remove certificates
:foreach certificate in=[/certificate find] do={
  :do {
    /certificate remove $certificate
    } on-error={}
  }

# Remove firewall rules, address-lists and NATs
:foreach rule in=[/ip firewall filter find where !dynamic] do={
  :do {
    /ip firewall filter remove $rule
    } on-error={}
  }
 :foreach addressList in=[/ip firewall address-list find where !dynamic] do={
  :do {
    /ip firewall address-list remove $addressList
    } on-error={}
  }
 :foreach natRule in=[/ip firewall nat find where !dynamic] do={
  :do {
    /ip firewall nat remove $natRule
    } on-error={}
  }

  # Bridges and vlan interfaces
  :foreach port in=[/interface bridge port find] do={
    :do {
      /interface bridge port remove $port
      } on-error={}
    }
  :foreach vlanIface in=[/interface vlan find] do={
    :do {
      /interface vlan remove $vlanIface
      } on-error={}
    }
  :foreach bridge in=[/interface bridge find] do={
    :do {
      /interface bridge remove $bridge
      } on-error={}
    }

# Reset interfaces names
:do {
  :foreach iface in=[/interface ethernet find] do={
    :do { /interface ethernet set $iface name=[get $iface default-name] } on-error={}
    :do { /interface ethernet set $iface master-port=none } on-error={}
    }
  }

# Remove interfaces IPs
:foreach ipAddress in=[/ip address find where !dynamic] do={
  :do {
    /ip address remove $ipAddress
    } on-error={}
  }

# Remove routes
:foreach route in=[/ip route find where !dynamic] do={
  :do {
    /ip route remove $route
    } on-error={}
  }

# Remove system logging and syslog
:do { /system logging remove [/system logging find where action="remoteSyslog" and topics="!dns"] } on-error={}
:do { /system logging remove [/system logging find where prefix="debug" and topics="wireless"] } on-error={}
:do { /system logging remove [/system logging find where prefix="debug" and topics="manager"] } on-error={}
:do { /system logging action remove [/system logging action find where name="remoteSyslog" and target="remote"] } on-error={}

# Remove DNS entries
:foreach dnsEntry in=[/ip dns static find where !dynamic] do={
  :do {
    /ip dns static remove $dnsEntry
    } on-error={}
  }


:put ""
:put "======================================================================"
:put " = Doing basic staging and system services configuration"
:put "======================================================================"

# Wait for interfaces to be up
  {
  :local count 0;
  :while ([/interface ethernet find] = "") do={
    :if ($count = 30) do={
      :put "Waiting for interfaces to be up..."
      :log warning "DefConf: Unable to find ethernet interfaces";
      /quit;
      }
    :delay 1s; :set count ($count +1);
    };
  }

:do { /port set 0 name=serial0 } on-error={}

/system routerboard settings
set boot-device=flash-boot protected-routerboot=disabled

/system identity
set name=$localFqdn

/user set 0 name=$"adminUserName"
/user set 0 password="$adminPassword"

:if ([:len $dnsServers] > 0) do={
    /ip dns set allow-remote-requests=yes servers="$dnsServers" cache-max-ttl=1d
    }

/ip dns static
add address=$administrationIp name="$localHostname"
add address=$administrationIp name="$localFqdn"

/ip cloud set update-time=no
/ip cloud set ddns-enabled=no
/ip upnp set enabled=no
/ip upnp set show-dummy-rule=no
/ip settings set rp-filter=strict
/ip neighbor discovery set discover-interface-list=none
/ip proxy set enabled=no
/ip socks set enabled=no

/ip service
set telnet disabled=yes
set api disabled=yes
set api-ssl disabled=yes
set telnet address="$authorizedAdminNetwork"
set api address="$authorizedAdminNetwork"
set api-ssl address="$authorizedAdminNetwork"
set ftp address="$authorizedAdminNetwork"
set www address="$authorizedAdminNetwork"
set winbox address="$authorizedAdminNetwork"
set www-ssl address="0.0.0.0/0"
set ssh address="0.0.0.0/0"
:do { /ip ssh set strong-crypto=yes } on-error={}
set www disabled=yes

/tool bandwidth-server set enabled=no
/tool mac-server set allowed-interface-list=none
/tool mac-server mac-winbox set allowed-interface-list=none
/tool mac-server ping set enabled=no

/system clock
set time-zone-autodetect=no
set time-zone-name="$timeZone"

:if ( ([:len $ntpServerIp1] > 0) and ([:len $ntpServerIp2] > 0) )  do={
  /system ntp client set enabled=yes primary-ntp="$ntpServerIp1" secondary-ntp="$ntpServerIp2"
} else={
  :if ([:len $ntpServerIp1] > 0) do={
    /system ntp client set enabled=yes primary-ntp="$ntpServerIp1"
    }
  }

:if ([:len $ntpServersFqdns] > 0) do={
  /system ntp client set enabled=yes server-dns-names="$ntpServersFqdns"
  }

:if ([:len $syslogServerIp] > 0) do={
  /system logging action add name=remoteSyslog remote="$syslogServerIp" target="remote"
  /system logging add action="remoteSyslog" topics="!dns"
  }

/system logging
add prefix="debug" topics="wireless"
add prefix="debug" topics="manager"

/interface bridge settings set allow-fast-path=yes use-ip-firewall=no use-ip-firewall-for-pppoe=no use-ip-firewall-for-vlan=no

:put ""
:put "========================================================================"
:put "=== Configuring bridges, vlan interfaces and associating them"
:put "========================================================================"

# Create bridges (associated to vlans)
/interface bridge add name=br-spanning-tree
:foreach vlanName,vlanId in=$vlanNamesConfig do={
  /interface bridge add name=("br-".$vlanName."-v".$vlanId)
  }

:if ($verboseConfig = "yes") do={ /interface bridge print brief }

# Create vlan interfaces
:foreach vlanName,vlanId in=$vlanNamesConfig do={
  :foreach iface in=($egressPortsToTagArray->$vlanId) do={
    /interface vlan add interface=$iface name=("vlif-".$vlanName."-".$iface."-v".$vlanId) vlan-id=$vlanId
    }
  }

:if ($verboseConfig = "yes") do={ /interface vlan print brief }

# Add vlan interfaces to the corresponding bridges
:foreach vlanName,vlanId in=$vlanNamesConfig do={
  :foreach iface in=($egressPortsToTagArray->$vlanId) do={
    #:put ("br-".$vlanName."-v".$vlanId."   "."vlif-".$vlanName."-".$iface."-v".$vlanId)
    /interface bridge port add bridge=("br-".$vlanName."-v".$vlanId) interface=("vlif-".$vlanName."-".$iface."-v".$vlanId)
    }
  }

:if ($verboseConfig = "yes") do={ /interface bridge port print brief }

# Add untagged ports to corresponding bridges
:foreach vlanName,vlanId in=$vlanNamesConfig do={
  :foreach iface in=([:toarray ($ingressPortsToTagArray->$vlanId)]) do={
    #:put ("br-".$vlanName."-v".$vlanId."  ".$iface)
    /interface bridge port add bridge=("br-".$vlanName."-v".$vlanId) interface=$iface
    }
  }

:if ($verboseConfig = "yes") do={ /interface bridge port print }

# Do not allow discovery
/ip neighbor discovery set discover-interface-list=none



:put ""
:put "======================================================================"
:put "= Configuring IP addresses and default route"
:put "======================================================================"

:foreach vlanName,ipAdressAndMaskSize in=$bridgesIps do={
  :if ([:len $ipAdressAndMaskSize] > 0) do={
    /ip address add address="$ipAdressAndMaskSize" interface=("br-".$vlanName."-v".($vlanNamesConfig->$vlanName))
    }
  }

:if ($verboseConfig = "yes") do={ /ip address print }

:if ([:len $defaultGw] > 0) do={
    /ip route add distance=1 gateway="$defaultGw"
    }

:if ($verboseConfig = "yes") do={ /ip route print }


:put ""
:put "======================================================================"
:put "= Configuring masquerading"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall nat
  add action=masquerade chain=srcnat log=yes log-prefix=out_masq out-interface=$internetBridgeNameConfig
  }



:put ""
:put "======================================================================"
:put "= Configuring adress-lists"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall address-list
  add address="$authorizedAdminNetwork" comment="Allowed IPs for this equipment managment " list=support

  add address=0.0.0.0/8 comment="Self-Identification [RFC 3330]" list=bogons
  add address=10.0.0.0/8 comment="Private[RFC 1918] - CLASS A # Check if you need this subnet before enable it" disabled=yes list=bogons
  add address=127.0.0.0/16 comment="Loopback [RFC 3330]" list=bogons
  add address=169.254.0.0/16 comment="Link Local [RFC 3330]" list=bogons
  add address=172.16.0.0/12 comment="Private[RFC 1918] - CLASS B # Check if you need this subnet before enable it" disabled=yes list=bogons
  add address=192.168.0.0/16 comment="Private[RFC 1918] - CLASS C # Check if you\_need this subnet before enable it" disabled=yes list=bogons
  add address=192.0.2.0/24 comment="Reserved - IANA - TestNet1" list=bogons
  add address=192.88.99.0/24 comment="6to4 Relay Anycast [RFC 3068]" list=bogons
  add address=198.18.0.0/15 comment="NIDB Testing" list=bogons
  add address=198.51.100.0/24 comment="Reserved - IANA - TestNet2" list=bogons
  add address=203.0.113.0/24 comment="Reserved - IANA - TestNet3" list=bogons
  add address=224.0.0.0/4 comment="MC, Class D, IANA # Check if you need this subnet before enable it" list=bogons

  /ip firewall address-list
  add address=0.0.0.0/8 comment=RFC6890 list=NotPublic
  add address=10.0.0.0/8 comment=RFC6890 list=NotPublic
  add address=100.64.0.0/10 comment=RFC6890 list=NotPublic
  add address=127.0.0.0/8 comment=RFC6890 list=NotPublic
  add address=169.254.0.0/16 comment=RFC6890 list=NotPublic
  add address=172.16.0.0/12 comment=RFC6890 list=NotPublic
  add address=192.0.0.0/24 comment=RFC6890 list=NotPublic
  add address=192.0.2.0/24 comment=RFC6890 list=NotPublic
  add address=192.168.0.0/16 comment=RFC6890 list=NotPublic
  add address=192.88.99.0/24 comment=RFC3068 list=NotPublic
  add address=198.18.0.0/15 comment=RFC6890 list=NotPublic
  add address=198.51.100.0/24 comment=RFC6890 list=NotPublic
  add address=203.0.113.0/24 comment=RFC6890 list=NotPublic
  add address=224.0.0.0/4 comment=RFC4601 list=NotPublic
  add address=240.0.0.0/4 comment=RFC6890 list=NotPublic
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : invalid packets dropping"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=separator comment="################################ DROP INVALID PACKETS"
  add action=drop chain=input comment="Drop input invalid packets" connection-state=invalid log=yes
  add action=drop chain=output comment="Drop output invalid packets" connection-state=invalid log=yes
  add action=drop chain=forward comment="Drop forward invalid packets" connection-state=invalid log=yes
  }


:put ""
:put "======================================================================"
:put "= Configuring firewall rules : attacks mitigation"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=comment comment="################################ ATTACKs MITIGATION"

  add chain=forward action=drop dst-address-list=bogons comment="Drop to bogon list"
  add action=drop chain=input comment="Drop all packets from public internet which should not exist in public network - input" in-interface="$internetBridgeNameConfig" src-address-list=NotPublic disabled=yes
  add action=drop chain=forward comment="Drop all packets from public internet which should not exist in public network -forward" in-interface="$internetBridgeNameConfig" dst-address-list=NotPublic disabled=yes
  add action=drop chain=output comment="Drop all packets to public internet which should not exist in public network - output" out-interface="$internetBridgeNameConfig" src-address-list=NotPublic disabled=yes

  add chain=input action=drop src-address-list=Port_Scanner comment="Drop to port scan list"
  add chain=forward action=drop dst-port=25,587 protocol=tcp src-address-list=spammers comment="Drop spammers"
  add chain=input action=drop protocol=tcp dst-port=22 src-address-list=ssh_blacklist comment="Drop ssh brute forcers" disabled=no
  add chain=input action=drop protocol=tcp dst-port=3389 src-address-list=rdp_blacklist comment="Drop RDP brute forcers" disabled=no
  add chain=input action=drop protocol=tcp dst-port=443 src-address-list=https_blacklist comment="Drop https brute forcers" disabled=no

  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp psd=21,3s,3,1 address-list-timeout=2w comment="Port scanners" disabled=no
  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp tcp-flags=fin,!syn,!rst,!psh,!ack,!urg address-list-timeout=2w comment="NMAP FIN Stealth scan"
  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp tcp-flags=fin,syn address-list-timeout=2w comment="SYN/FIN scan"
  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp tcp-flags=syn,rst address-list-timeout=2w comment="SYN/RST scan"
  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp tcp-flags=fin,psh,urg,!syn,!rst,!ack address-list-timeout=2w comment="FIN/PSH/URG scan"
  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp tcp-flags=fin,syn,rst,psh,ack,urg address-list-timeout=2w comment="ALL/ALL scan"
  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp tcp-flags=!fin,!syn,!rst,!psh,!ack,!urg address-list-timeout=2w comment="NMAP NULL scan"

  add chain=forward action=add-src-to-address-list address-list=spammers address-list-timeout=3h connection-state=new connection-limit=30,32 dst-port=25,587 limit=30/1m,0:packet protocol=tcp comment="Add Spammers to the list for 3 hours"

  add chain=input action=add-src-to-address-list address-list=ssh_blacklist protocol=tcp dst-port=22 connection-state=new src-address-list=ssh_stage3 address-list-timeout=1d comment="Add SSH brute forcer to ssh_blacklist list" disabled=no
  add chain=input action=add-src-to-address-list address-list=ssh_stage3 protocol=tcp dst-port=22 connection-state=new src-address-list=ssh_stage2 address-list-timeout=1m comment="Add SSH brute forcer to ssh_stage3 list" disabled=no
  add chain=input action=add-src-to-address-list address-list=ssh_stage2 protocol=tcp dst-port=22 connection-state=new src-address-list=ssh_stage1 address-list-timeout=1m comment="Add SSH brute forcer to ssh_stage2 list" disabled=no
  add chain=input action=add-src-to-address-list address-list=ssh_stage1 protocol=tcp dst-port=22 connection-state=new address-list-timeout=1m comment="Add SSH brute forcer to ssh_stage1 list" disabled=no

  add chain=input action=add-src-to-address-list address-list=rdp_blacklist protocol=tcp dst-port=3389 connection-state=new src-address-list=rdp_stage4 address-list-timeout=1d comment="Add RDP brute forcer to rdp_blacklist list" disabled=no
  add chain=input action=add-src-to-address-list address-list=rdp_stage4 protocol=tcp dst-port=3389 connection-state=new src-address-list=rdp_stage3 address-list-timeout=1m comment="Add RDP brute forcer to rdp_stage4 list" disabled=no
  add chain=input action=add-src-to-address-list address-list=rdp_stage3 protocol=tcp dst-port=3389 connection-state=new src-address-list=rdp_stage2 address-list-timeout=1m comment="Add RDP brute forcer to rdp_stage3 list" disabled=no
  add chain=input action=add-src-to-address-list address-list=rdp_stage2 protocol=tcp dst-port=3389 connection-state=new src-address-list=rdp_stage1 address-list-timeout=1m comment="Add RDP brute forcer to rdp_stage2 list" disabled=no
  add chain=input action=add-src-to-address-list address-list=rdp_stage1 protocol=tcp dst-port=3389 connection-state=new address-list-timeout=1m comment="Add RDP brute forcer to rdp_stage1 list" disabled=no

  add chain=input action=add-src-to-address-list address-list=https_blacklist address-list-timeout=1h connection-state=new connection-limit=30,32 dst-port=443 limit=5/1m,0:packet protocol=tcp comment="Add HTTPS brute forcer to https_blacklist list"
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : established/related"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=comment comment="################################ ESTABLISHED / RELATED"
  add chain=input comment="Accept established/related connections/packets" connection-state=established,related
  add chain=forward comment="Accept established/related connections/packets" connection-state=established,related
  add chain=output comment="Accept established/related connections/packets" connection-state=established,related
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : input"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=comment comment="################################ INPUT"
  add action=drop chain=input comment="Drop all access to FW admin - except to support list" dst-port=21,22,23,80,443,8291,8728,8729 protocol=tcp src-address-list=!support

  add action=drop chain=input comment="Drop MT Discovery Protocol" dst-port=5678 protocol=udp
  add action=accept chain=input comment="Allow full access to SUPPORT address list" log-prefix=support-access src-address-list=support
  add action=accept chain=input comment="Allow localhost traffic" dst-address=127.0.0.1 src-address=127.0.0.1
  add action=accept chain=input comment="Allow Broadcast Traffic" dst-address-type=broadcast
  add action=accept chain=input comment="Allow UPnP udp/1900" dst-port=1900 protocol=udp disabled=yes
  add action=accept chain=input comment="Allow UPnP tcp/2828" dst-port=2828 protocol=tcp disabled=yes
  add action=accept chain=input comment="Allow SNMP requests from support tcp/161" dst-port=161 protocol=tcp src-address-list=support
  add action=accept chain=input comment="Allow SNMP requests from support udp/161" dst-port=161 protocol=udp src-address-list=support

  add action=accept chain=input comment="Allow DHCP requests from clients" src-port=68 dst-port=67 in-interface="!$internetBridgeNameConfig" protocol=udp
  add action=accept chain=input comment="Allow DHCP answers from others" src-port=67 dst-port=68 in-interface="!$internetBridgeNameConfig" protocol=udp
  add action=accept chain=input comment="Allow DNS requests from clients udp/53" dst-port=53 protocol=udp in-interface="!$internetBridgeNameConfig"
  add action=accept chain=input comment="Allow DNS requests from clients tcp/53" dst-port=53 protocol=tcp in-interface="!$internetBridgeNameConfig"
  add action=accept chain=input comment="Allow NTP requests from clients" dst-port=123 protocol=udp in-interface="!$internetBridgeNameConfig"
  add action=accept chain=input comment="Allow Web Proxy requests from clients" dst-port=8080 protocol=tcp disabled=yes
  add action=accept chain=input comment="Allow Socks requests from clients for Hotspot" dst-port=1080 protocol=tcp disabled=yes
  add action=accept chain=input comment="AllowBandwidth server requests from clients" dst-port=2000 protocol=tcp disabled=yes

  add action=accept chain=input comment="Allow PPTP connections from clients (tcp/1723)" dst-port=1723 protocol=tcp disabled=yes
  add action=accept chain=input comment="Allow PPTP and EoIP connections from clients (gre)" protocol=gre disabled=yes
  add action=accept chain=input comment="Allow IPIP connections from clients" protocol=ipencap disabled=yes
  add action=accept chain=input comment="Allow IPSec connections from clients (IKE)" dst-port=500 protocol=udp disabled=yes
  add action=accept chain=input comment="Allow IPSec connections from clients (ESP)" protocol=ipsec-esp disabled=yes
  add action=accept chain=input comment="Allow IPSec connections from clients (AH)" protocol=ipsec-ah disabled=yes
  add action=accept chain=input comment="Allow OpenVPN connections from clients tcp/1194" dst-port=1194 protocol=tcp disabled=yes
  add action=accept chain=input comment="Allow OpenVPN connections from clients udp/1194" dst-port=1194 protocol=udp disabled=yes

  add action=accept chain=input comment="Allow RIP connections from others" dst-port=520-521 protocol=udp disabled=yes
  add action=accept chain=input comment="Allow OSPF connections from others" protocol=ospf disabled=yes
  add action=accept chain=input comment="Allow BGP connections from others" dst-port=179 protocol=tcp disabled=yes
  add action=accept chain=input comment="Allow BGP connections from others" dst-port=5000-5100 protocol=udp disabled=yes

  add action=jump chain=input comment="Jump for icmp input flow" jump-target=ICMP protocol=icmp
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : output"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=comment comment="################################ OUTPUT"
  add action=accept chain=output comment="Allow localhost traffic" dst-address=127.0.0.1 src-address=127.0.0.1
  add action=accept chain=output comment="Allow Broadcast Traffic" dst-address-type=broadcast
  add action=accept chain=output comment="Allow UPnP udp/1900" dst-port=1900 protocol=udp disabled=yes
  add action=accept chain=output comment="Allow UPnP tcp/2828" dst-port=2828 protocol=tcp disabled=yes
  add action=accept chain=output comment="Allow SNMP traps outgoing tcp/162" dst-port=162 protocol=tcp dst-address-list=support
  add action=accept chain=output comment="Allow SNMP traps outgoing udp/162" dst-port=162 protocol=udp dst-address-list=support

  add action=accept chain=output comment="Allow DHCP requests from firewall" src-port=68 dst-port=67 protocol=udp
  add action=accept chain=output comment="Allow DHCP answers from firewall" src-port=67 dst-port=68 protocol=udp
  add action=accept chain=output comment="Allow DNS requests from firewall udp/53" dst-port=53 protocol=udp
  add action=accept chain=output comment="Allow DNS requests from firewall tcp/53" dst-port=53 protocol=tcp
  add action=accept chain=output comment="Allow NTP requests from firewall" dst-port=123 protocol=udp

  add action=accept chain=output comment="Allow WEB requests from firewall" dst-port=80,8080,443 protocol=tcp
  :if ([:len $syslogServerIp] > 0) do={
    add action=accept chain=output comment="Allow Syslog sending to syslog server tcp/514" dst-address="$syslogServerIp" dst-port=514 protocol=tcp
    add action=accept chain=output comment="Allow Syslog sending to syslog server udp/514" dst-address="$syslogServerIp" dst-port=514 protocol=udp
    }

  add action=accept chain=output comment="Allow PPTP connections from firewall (tcp/1723)" dst-port=1723 protocol=tcp disabled=yes
  add action=accept chain=output comment="Allow PPTP and EoIP connections from firewall (gre)" protocol=gre disabled=yes
  add action=accept chain=output comment="Allow IPIP connections from firewall" protocol=ipencap disabled=yes
  add action=accept chain=output comment="Allow IPSec connections from firewall (IKE)" dst-port=500 protocol=udp disabled=yes
  add action=accept chain=output comment="Allow IPSec connections from firewall (ESP)" protocol=ipsec-esp disabled=yes
  add action=accept chain=output comment="Allow IPSec connections from firewall (AH)" protocol=ipsec-ah disabled=yes
  add action=accept chain=output comment="Allow OpenVPN connections from firewall tcp/1194" dst-port=1194 protocol=tcp disabled=yes
  add action=accept chain=output comment="Allow OpenVPN connections from firewall udp/1194" dst-port=1194 protocol=udp disabled=yes

  add action=accept chain=output comment="Allow RIP connections to others" dst-port=520-521 protocol=udp disabled=yes
  add action=accept chain=output comment="Allow OSPF connections to others" protocol=ospf disabled=yes
  add action=accept chain=output comment="Allow BGP connections to others" dst-port=179 protocol=tcp disabled=yes
  add action=accept chain=output comment="Allow BGP connections to others" dst-port=5000-5100 protocol=udp disabled=yes

  add action=jump chain=output comment="Jump for icmp output" jump-target=ICMP protocol=icmp
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : forward"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=separator comment="################################ FORWARD"
  add action=drop chain=forward comment="Drop uTorrent" dst-port=53658 protocol=tcp  disabled=yes
  add action=drop chain=forward comment="Drop DC++ tcp/13336" dst-port=13336 protocol=tcp disabled=yes
  add action=drop chain=forward comment="Drop DC++ tcp/19030" dst-port=19030 protocol=tcp disabled=yes
  add action=drop chain=forward comment="Drop DC++ udp/12620" dst-port=12620 protocol=udp  disabled=yes
  add action=jump chain=forward comment="Jump for icmp forward flow" jump-target=ICMP protocol=icmp
  add chain=forward comment="Accept Internet outgoing" out-interface="$internetBridgeNameConfig"
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : ICMP chain"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=comment comment="################################ ICMP"
  add action=accept chain=ICMP comment="Echo request - Avoiding Ping Flood" icmp-options=8:0 limit=1,5:packet protocol=icmp
  add action=accept chain=ICMP comment="Echo reply" icmp-options=0:0 protocol=icmp
  add action=accept chain=ICMP comment="Time Exceeded" icmp-options=11:0 protocol=icmp
  add action=accept chain=ICMP comment="Destination unreachable" icmp-options=3:0-1 protocol=icmp
  add action=accept chain=ICMP comment=PMTUD icmp-options=3:4 protocol=icmp
  add action=drop chain=ICMP comment="Drop to the other ICMPs" protocol=icmp
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : final rejects/drops"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=comment comment="################################ FINAL REJECT / DROP"
  add action=reject chain=input in-interface="!$internetBridgeNameConfig" log=yes log-prefix=reject:input reject-with=icmp-admin-prohibited
  add action=reject chain=forward in-interface="!$internetBridgeNameConfig" log=yes log-prefix=reject:forward reject-with=icmp-admin-prohibited
  add action=reject chain=output log=yes log-prefix=reject:output out-interface="!$internetBridgeNameConfig" reject-with=icmp-admin-prohibited
  add action=drop chain=input log=yes log-prefix=drop:input
  add action=drop chain=forward log=yes log-prefix=drop:forward
  add action=drop chain=output log=yes log-prefix=drop:output
  }


:put ""
:put "======================================================================"
:put " = HTTPS certificate generation (takes some time...)"
:put "======================================================================"

/certificate
add name="catmpl-$localHostname" common-name="ca-$localHostname" key-usage=key-cert-sign,crl-sign days-valid=10000 key-size=2048
add name="fwtmpl-$localHostname" common-name="$localFqdn"  days-valid=10000 key-size=2048
sign "catmpl-$localHostname" ca-crl-host=127.0.0.1 name="ca-$localHostname"
:delay 1s
sign ca="ca-$localHostname" "fwtmpl-$localHostname" name="$localHostname"
:delay 1s
set "ca-$localHostname" trusted=yes
set "$localHostname" trusted=yes
export-certificate "ca-$localHostname"
/ip service set www-ssl certificate="$localHostname" disabled=no

# Wait for certificates to be created
  {
  :local count 0;
  :while ([/certificate find where name="$localHostname"] = "") do={
    :if ($count = 30) do={
      /quit;
      }
    :delay 1s; :set count ($count +1);
    };
  }



:put ""
:put "========================================================================"
:put "=== Destroying defined global variables"
:put "========================================================================"

:set vlanNamesConfig
:set bridgesIps
:set adminVlanNameConfig
:set internetVlanNameConfig
:set internetBridgeNameConfig
:set vlansConfig
:set functionnalModeConfig
:set verboseConfig
:set keyInSimpleArray
:set keyInArray
:set vlanNameArray
:set localEthernetInterfaces
:set egressPortsToTagArray
:set ingressPortsToTagArray
:set configurationOk
:set administrationIp
:set defaultGw
:set localHostname
:set localFqdn
:set dnsServers
:set timeZone
:set ntpServerIp1
:set ntpServerIp2
:set ntpServersFqdns
:set syslogServerIp
:set adminUserName
:set adminPassword
:set authorizedAdminNetwork



:put ""
:put "========================================================================"
:put "=== End of script noise"
:put "========================================================================"

 :for i from=500 to=10000 step=500 do={
   :beep frequency=$i length=11ms;
   :delay 11ms;
 }
 :delay 50ms;
 :for i from=500 to=10000 step=500 do={
   :beep frequency=$i length=11ms;
   :delay 11ms;
 }
 :delay 50ms;
 :for i from=500 to=10000 step=500 do={
   :beep frequency=$i length=11ms;
   :delay 11ms;
 }
 
ghusson
just joined
Topic Author
Posts: 5
Joined: Thu Mar 01, 2018 11:41 am

Re: Staging script example

Tue Jul 03, 2018 4:21 pm

New version of the script, compatible with 6.42+ RouterOS.
Still a big TODO list, DHCP server configuration for example.
But this script saves several hours at each uses.
Feel free to propose enhancements !
BR Gautier HUSSON - Liberasys

# ====== Initial Mikrotik configuration template ======
# By Gautier HUSSON - HUSSON CONSULTING SAS - Liberasys (Britany, FRANCE)
# contact_web@liberasys.com - www.liberasys.com
# Revision : 0.4 / 20180316
# Status : not much tested, please prepare your serial console or USB/WIFI dongle !

#TODO : ethernet : configure loop protection (check if bug correction is OK)
#TODO : check vlan names between differents arrays
#TODO : verify we have at last one port associated to admin vlan
#TODO : firewall : implement DNS resolution in access-lists
#TODO : firewall : optimisation for : established/related sooner, add some connection state = new
#TODO : firewall : add a generic function that create rules for brute force mitigation over TCP and input a list of ports (ex : 3389)
#TODO : Certificates : generates new ones only if olders are bad
#TODO : check that master port is defined in vlansConfig
#TODO : check functionnalModeConfig // switch mode and VLAN unaware chip
#TODO : bridges : add DHCP server/client configuration an apply it
#TODO : look at HTTPs protection, maybe disallow it from all

# Disclaimer of Warranty.
#  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
# APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
# HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
# OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
# IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
# ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

# Limitation of Liability.
#  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
# WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
# THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
# GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
# USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
# DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
# PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
# EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGES.

# ======================================================================
# TIPS with scripts (or /import for syntax check) - thanks to Martin S. from Mikrotik :-) :
# ======================================================================
# Create and edit system script with CLI :
# Remark : you can otherwise import them from file.
#   /system script remove staging
#   /system script add name=staging
#   /system script edit staging source
#   paste your script
#   Ctrl+o
# Review your syntax :
#   /system script edit staging source
#   other solution :
#   /system script print where name=staging
# Run your script :
#   /system script run staging

# ======================================================================
# = Advices
# ======================================================================
# 1) change parameters here under in "Input variables" paragraph
# 2) either :
#    - start from blank configuration (use serial terminal):
#      /system reset-configuration no-defaults=yes
#      with serial line, pass lines with copy/paste
#      do it by paragraphs or serial line will give errors - buffer ov maybe
#      (sudo screen /dev/ttyUSB0 115200)
#    - upload the file (.rsc) on your mikrotik
#      CLI : /system reset-configuration no-defaults=yes run-after-reset=<my_filename.rsc>
#    - apply with /import or script run, at your risk (can cut legs !)



:put ""
:put "========================================================================"
:put "=== Setting environment global variables"
:put "========================================================================"

# Remark : everywhere there is an IP, you can put nothing ("") and the configurations using
#          the IP will be bypassed. Everywhere but authorizedAdminNetwork ! :-)

# functionnalModeConfig defines the mode of configuration
# 3 possible values :
#  - "switch" : the adminVlanNameConfig only will have an IP, and no routing will be configured
#  - "router" : all the VLANs will be forwarded and the OS will do routing
#  - "firewall" : all the VLANs will be forwarded and the routing will be firewalled
:global functionnalModeConfig "switch"

# /!\  !!! CHANGE ME !!!!  /!\ :
:global adminUserName "miktikadm"
:global adminPassword "miktikadm31337"
# /!\  !!! CHANGE ME !!!!  /!\ :

# vlan names definition (will be used in bridge names and vlan interfaces too)
:global vlanNamesConfig {
                        "liberasys_lan"="250";
                        "liberasys_dmz"="210";
                        "liberasys_dmz_tiers"="220";
                        "liberasys_invite"="205";
                        "liberasys_lab"="207";
                        "creafab_lan"="5";
                        "internet_uplink"="200";
                        }
:global adminVlanNameConfig "liberasys_lan"
:global internetVlanNameConfig "internet_uplink"


# Ips on bridges :
:global bridgesIps {
                   "liberasys_lan"="192.168.250.80/24";
                   }

# vlan definition per interface
# special data structure in order do describe wanted configuration
# for vlans array, the special value "all" is replaced by each vlan
:global vlansConfig {
                    ether1={mode="untagged"; vlans={"liberasys_lan";};};
                    ether2={mode="untagged"; vlans={"liberasys_lan";};};
                    ether3={mode="untagged"; vlans={"liberasys_lan";};};
                    ether4={mode="untagged"; vlans={"liberasys_lan";};};
                    ether5={mode="untagged"; vlans={"liberasys_dmz";};};
                    ether6={mode="untagged"; vlans={"liberasys_dmz";};};
                    ether7={mode="untagged"; vlans={"liberasys_dmz_tiers";};};
                    ether8={mode="untagged"; vlans={"liberasys_dmz_tiers";};};
#                    ether9={mode="untagged"; vlans={"data";};};
#                    ether10={mode="untagged"; vlans={"services";};};
#                    ether11={mode="untagged"; vlans={"services";};};
#                    ether12={mode="untagged"; vlans={"services";};};
#                    ether13={mode="untagged"; vlans={"services";};};
#                    ether14={mode="untagged"; vlans={"services";};};
#                    ether15={mode="untagged"; vlans={"services";};};
#                    ether16={mode="untagged"; vlans={"services";};};
#                    ether17={mode="untagged"; vlans={"services";};};
#                    ether18={mode="untagged"; vlans={"services";};};
#                    ether19={mode="untagged"; vlans={"services";};};
#                    ether20={mode="untagged"; vlans={"services";};};
#                    ether21={mode="trunk"; vlans={"admin"; "data"; "services"};};
#                    ether22={mode="tagged";vlans={"internet"};};
#                    ether23={mode="untagged"; vlans={"internet";};};
#                    ether24={mode="trunk"; vlans={"all";};};
#                    sfp1={mode="trunk"; vlans={"all";};};
#                    sfp2={mode="trunk"; vlans={"all";};};
#                    sfp3={mode="trunk"; vlans={"all";};};
#                    sfp4={mode="trunk"; vlans={"all";};};
                    sfp9={mode="trunk"; vlans={"all";};};
                    sfp10={mode="trunk"; vlans={"all";};};
                    sfp11={mode="trunk"; vlans={"all";};};
                    sfp12={mode="trunk"; vlans={"all";};};
                    }


:global localFqdn "plmasw01.liberasys.com";
:global timeZone "Europe/Paris"
:global authorizedAdminNetwork "192.168.0.0/16"
:global defaultGw "192.168.250.254"
:global dnsServers "192.168.250.254,192.168.200.254"
:global ntpServerIp1 "37.187.56.220"
:global ntpServerIp2 "5.135.3.88"
:global ntpServersFqdns "0.fr.pool.ntp.org,1.fr.pool.ntp.org,2.fr.pool.ntp.org,3.fr.pool.ntp.org"
:global syslogServerIp "192.168.210.10"

# verboseConfig : "yes" or "no"
:global verboseConfig "yes"

# DON'T TOUCH THOSE VARIABLES :
:global configurationOk "true"



# ======================================================================
# = Copyright and SOS beeps
# ======================================================================

# Initial delay, if system is booting, it is mandatory
#:delay 20s;

:put "====== Initial Mikrotik configuration template ======"
:put "By Gautier HUSSON - HUSSON CONSULTING SAS - Liberasys"
:put "License : CC BY 4.0"
:put "          https://creativecommons.org/licenses/by/4.0/"
:put ""
:put "WARNING WARNING WARNING WARNING WARNING WARNING"
:put "WARNING WARNING WARNING WARNING WARNING WARNING"
:put "WARNING WARNING WARNING WARNING WARNING WARNING"
:put ""
:put "You will loose almost all your configuration."
:put "You have 5 seconds to quit (Ctrl + C)."
:put ""
:delay 0.2s
:beep length=0.1s
:delay 0.2s
:beep length=0.1s
:delay 0.2s
:beep length=0.1s

:delay 0.5s
:beep length=0.3s
:delay 0.5s
:beep length=0.3s
:delay 0.5s
:beep length=0.3s
:delay 0.5s

:beep length=0.1s
:delay 0.2s
:beep length=0.1s
:delay 0.2s
:beep length=0.1s
:delay 0.5s



:put ""
:put "========================================================================"
:put "=== Defining internal functions"
:put "========================================================================"

# keyInSimpleArray: returns true or false
# arg1: key name
# arg2: array (without values attached to keys)
# use example: :put [$keyInArray "plop" $localEthernetInterfaces]
:global keyInSimpleArray do={
  :local arraySize [:len $2]
  :if ( $arraySize = 0) do={ :return "false"; };
  :foreach key in=$2 do={
    :if ($1 = $key) do={ :return "true"; };
    }
  :return "false";
  }

# keyInArray: returns true or false
# arg1: key name
# arg2: array (with values attached to keys)
# use example: :put [$keyInArray "plop" $localEthernetInterfaces]
:global keyInArray do={
  :local arraySize [:len $2]
  :if ( $arraySize = 0) do={ :return "false"; };
  :foreach key,value in=$2 do={
    :if ($1 = $key) do={ :return "true"; };
    }
  :return "false";
  }



:put ""
:put "========================================================================"
:put "=== Generating some variables"
:put "========================================================================"

# Compute administration IP
:global administrationIp
:set administrationIp
:global administrationIp
:set administrationIp [:pick ($bridgesIps->$adminVlanNameConfig) 0 [:find ($bridgesIps->$adminVlanNameConfig) "/"]]


# Compute Internet bridge name
:global internetBridgeNameConfig
:set internetBridgeNameConfig
:global internetBridgeNameConfig
:set internetBridgeNameConfig ("br-".$internetVlanNameConfig."-v".($vlanNamesConfig->$internetVlanNameConfig))


# Compute hostname
:global localHostname;
:set localHostname;
:global localHostname;
:set localHostname [:pick ($localFqdn) 0 [:find ($localFqdn) "."]];


# Replace vlan "all" by each vlan in vlansConfig
:global vlanNameArray
:set vlanNameArray
:global vlanNameArray
:foreach vlanName,vlanId in=$vlanNamesConfig do={
  :set vlanNameArray ($vlanNameArray, $vlanName)
  }
:foreach iface,conf in=$vlansConfig do={
  :foreach vlan in=($conf->"vlans") do={
    :if (vlan = "all") do={
      :set ($conf->"vlans") $vlanNameArray
      }
    }
  }


# Create table of all ethernet interfaces
:global localEthernetInterfaces
:set localEthernetInterfaces
:global localEthernetInterfaces
:foreach ifaceIndex in=[/interface find where type="ether"] do={
  #:put [/interface ethernet get value-name=default-name number=$ifaceIndex]
  :set localEthernetInterfaces ($localEthernetInterfaces, [/interface ethernet get value-name=default-name number=$ifaceIndex])
  }
#:put [:tostr $localEthernetInterfaces]
#:environment print


# Create array for EGRESS ports TO TAG : vlan -> interfaces list
:global egressPortsToTagArray
:set egressPortsToTagArray
:global egressPortsToTagArray ([:toarray ""])
:foreach iface,conf in=$vlansConfig do={
  :if ($conf->"mode" = "tagged" or $conf->"mode" = "trunk") do={
    :foreach vlan in=($conf->"vlans") do={
      #:put ($iface.":".($conf->"mode")." : ".$vlan)
      :set ($egressPortsToTagArray->($vlanNamesConfig->$vlan))  (($egressPortsToTagArray->($vlanNamesConfig->$vlan)).$iface.",")
      }
    }
  }
# translate sub arrays in form of values to arrays
:foreach vlanId,ifaces in=$egressPortsToTagArray do={
  :set ($egressPortsToTagArray->$vlanId)  ([:toarray ($egressPortsToTagArray->$vlanId)])
  }


# Create array for INGRESS ports TO TAG : vlan -> interfaces list (same begin as egressPortsToTagArray, with only untagged ports)
:global ingressPortsToTagArray;
:set $ingressPortsToTagArray;
:global ingressPortsToTagArray ([:toarray ""]);
:foreach iface,conf in=$vlansConfig do={
  :if ($conf->"mode" = "untagged") do={
    :foreach vlan in=($conf->"vlans") do={
      :set ($ingressPortsToTagArray->($vlanNamesConfig->$vlan))  (($ingressPortsToTagArray->($vlanNamesConfig->$vlan)).$iface.",")
      }
    }
  }
  # translate sub arrays in form of values to arrays
  :foreach vlanId,ifaces in=$ingressPortsToTagArray do={
    :set ($ingressPortsToTagArray->$vlanId)  ([:toarray ($ingressPortsToTagArray->$vlanId)])
    }



:put ""
:put "========================================================================"
:put "=== Checking input variables"
:put "========================================================================"

# Print the VLANS definitions
:if ($verboseConfig = "yes") do={
  :put "===  vlansConfig :"
  :foreach key,value in=$vlansConfig do={
    :put ($key." (".([:tostr ($value->"mode")]).")")
    :foreach key2 in=($value->"vlans") do={
      :put ("  ".([:tostr ($key2)]))
      }
    }
  }

# Print the interfaces per vlan table
:if ($verboseConfig = "yes") do={
  :put "===  egressPortsToTagArray :"
  :foreach vlanId,ifaces in=$egressPortsToTagArray do={
    :put ("Vlan : ".$vlanId)
    :foreach iface in=$ifaces do={
      :put ("  ".$iface)
      }
    }
  }

# Check that the authorizedAdminNetwork IP is filled
:if ($configurationOk = "true") do={
  :if ([:len $authorizedAdminNetwork] < 7) do={
    :put ("!!!!!!!! Invalid IP for $authorizedAdminNetwork, your equipment will be unmanageable")
    :beep frequency=220 length=2s
    :set configurationOk "false"
    }
  }

# Check bridges IPs : there should be at last one IP in the administration VLAN
:if ($configurationOk = "true") do={
  :if ([:len ($bridgesIps->$adminVlanNameConfig)] < 1) do={
    :put ("!!!!!!!! No IP configured on admin bridge, your equipment will be unmanageable")
    :beep frequency=220 length=2s
    :set configurationOk "false"
    }
  }

# Check bridges IPs : in switch mode, only the admin bridge should have an IP
:if ($configurationOk = "true") do={
  :if ($functionnalModeConfig = "switch") do={
    :if ([:len $bridgesIps] != 1) do={
      :put ("!!!!!!!! Too many IPs configured on bridges")
      :beep frequency=220 length=2s
      :set configurationOk "false"
      }
    }
  }

# Check vlansConfig array : interface names
:if ($configurationOk = "true") do={
  :foreach key,value in=$vlansConfig do={
    :if (!([$keyInSimpleArray $key $localEthernetInterfaces] = "true")) do={
      :put ("!!!!!!!! Invalid interface found: ".$key)
      :beep frequency=220 length=2s
      :set configurationOk "false"
      }
    }
  }

# Check vlansConfig array : mode
:if ($configurationOk = "true") do={
  :foreach key,value in=$vlansConfig do={
    :if ($value->"mode" != "untagged" and $value->"mode" != "tagged" and $value->"mode" != "trunk") do={
      :put ("!!!!!!!! Invalid mode found: \"".$value->"mode"."\" for \"".$key."\" interface")
      :beep frequency=220 length=2s
      :set configurationOk "false"
      }
    }
  }

# Check vlansConfig array : vlans number
:if ($configurationOk = "true") do={
  :foreach key,value in=$vlansConfig do={
    :local vlanNumber ([:len ($value->"vlans")])
    #:put ("vlan number for ".$key." : ".$vlanNumber)
    :if ($value->"mode" = "untagged" or $value->"mode" = "tagged") do={
      :if ([:len ($value->"vlans")] != 1) do={
        :put ("!!!!!!!! Invalid vlan numbers found for ".$key." (".$vlanNumber." vlans for ".($value->"mode")." mode : ".[:tostr ($value->"vlans")]." )")
        :beep frequency=220 length=2s
        :set configurationOk "false"
        }
      }
    :if ($value->"mode" = "trunk") do={
      :if ([:len ($value->"vlans")] < 1) do={
        :put ("!!!!!!!! Invalid vlan numbers found for ".$key." (".$vlanNumber." vlans for ".($value->"mode")." mode )")
        :beep frequency=220 length=2s
        :set configurationOk "false"
        }
      }
    }
  }

# Check vlansConfig array : vlans names
:if ($configurationOk = "true") do={
  :foreach key,value in=$vlansConfig do={
    :foreach key2 in=($value->"vlans") do={
      #:put ($key." ".$key2)
      :if (!([$keyInArray $key2 $vlanNamesConfig] = "true")) do={
        :put ("!!!!!!!! Invalid vlan name found : ".$key2." for ".$key)
        :beep frequency=220 length=2s
        :set configurationOk "false"
        }
      }
    }
  }

# Check functionnalModeConfig value
:if ($configurationOk = "true") do={
  :if ($functionnalModeConfig != "switch" and $functionnalModeConfig != "router" and $functionnalModeConfig != "firewall") do={
    :put ("!!!!!!!! Invalid functionnal name found : ".$functionnalModeConfig.". Possible values : switch, service, firewall")
    :beep frequency=220 length=2s
    :set configurationOk "false"
    }
  }

# Get out if configuration is bad
:if ($configurationOk = "false") do={
  :return "Bad configuration detected, abording !"
  }



:put ""
:put "========================================================================"
:put "=== Removing existing conflictual configuration - for idempotency"
:put "========================================================================"

# Remove certificates
:foreach certificate in=[/certificate find] do={
  :do {
    /certificate remove $certificate
    } on-error={}
  }

# Remove firewall rules, address-lists and NATs
:foreach rule in=[/ip firewall filter find where !dynamic] do={
  :do {
    /ip firewall filter remove $rule
    } on-error={}
  }
 :foreach addressList in=[/ip firewall address-list find where !dynamic] do={
  :do {
    /ip firewall address-list remove $addressList
    } on-error={}
  }
 :foreach natRule in=[/ip firewall nat find where !dynamic] do={
  :do {
    /ip firewall nat remove $natRule
    } on-error={}
  }

  # Bridges and vlan interfaces
  :foreach port in=[/interface bridge port find] do={
    :do {
      /interface bridge port remove $port
      } on-error={}
    }
  :foreach vlanIface in=[/interface vlan find] do={
    :do {
      /interface vlan remove $vlanIface
      } on-error={}
    }
  :foreach bridge in=[/interface bridge find] do={
    :do {
      /interface bridge remove $bridge
      } on-error={}
    }

# Reset interfaces names
:do {
  :foreach iface in=[/interface ethernet find] do={
    :do { /interface ethernet set $iface name=[get $iface default-name] } on-error={}
    :do { /interface ethernet set $iface master-port=none } on-error={}
    }
  }

# Remove interfaces IPs
:foreach ipAddress in=[/ip address find where !dynamic] do={
  :do {
    /ip address remove $ipAddress
    } on-error={}
  }

# Remove routes
:foreach route in=[/ip route find where !dynamic] do={
  :do {
    /ip route remove $route
    } on-error={}
  }

# Remove system logging and syslog
:do { /system logging remove [/system logging find where action="remoteSyslog" and topics="!dns"] } on-error={}
:do { /system logging remove [/system logging find where prefix="debug" and topics="wireless"] } on-error={}
:do { /system logging remove [/system logging find where prefix="debug" and topics="manager"] } on-error={}
:do { /system logging action remove [/system logging action find where name="remoteSyslog" and target="remote"] } on-error={}

# Remove DNS entries
:foreach dnsEntry in=[/ip dns static find where !dynamic] do={
  :do {
    /ip dns static remove $dnsEntry
    } on-error={}
  }


:put ""
:put "======================================================================"
:put " = Doing basic staging and system services configuration"
:put "======================================================================"

# Wait for interfaces to be up
  {
  :local count 0;
  :while ([/interface ethernet find] = "") do={
    :if ($count = 30) do={
      :put "Waiting for interfaces to be up..."
      :log warning "DefConf: Unable to find ethernet interfaces";
      /quit;
      }
    :delay 1s; :set count ($count +1);
    };
  }

:do { /port set 0 name=serial0 } on-error={}

/system routerboard settings
set boot-device=flash-boot protected-routerboot=disabled

/system identity
set name=$localFqdn

/user set 0 name=$"adminUserName"
/user set 0 password="$adminPassword"

:if ([:len $dnsServers] > 0) do={
    /ip dns set allow-remote-requests=yes servers="$dnsServers" cache-max-ttl=1d
    }

/ip dns static
add address=$administrationIp name="$localHostname"
add address=$administrationIp name="$localFqdn"

/ip cloud set update-time=no
/ip cloud set ddns-enabled=no
/ip upnp set enabled=no
/ip upnp set show-dummy-rule=no
/ip settings set rp-filter=strict
/ip neighbor discovery set discover-interface-list=none
/ip proxy set enabled=no
/ip socks set enabled=no

/ip service
set telnet disabled=yes
set api disabled=yes
set api-ssl disabled=yes
set telnet address="$authorizedAdminNetwork"
set api address="$authorizedAdminNetwork"
set api-ssl address="$authorizedAdminNetwork"
set ftp address="$authorizedAdminNetwork"
set www address="$authorizedAdminNetwork"
set winbox address="$authorizedAdminNetwork"
set www-ssl address="0.0.0.0/0"
set ssh address="0.0.0.0/0"
:do { /ip ssh set strong-crypto=yes } on-error={}
set www disabled=yes

/tool bandwidth-server set enabled=no
/tool mac-server set allowed-interface-list=none
/tool mac-server mac-winbox set allowed-interface-list=none
/tool mac-server ping set enabled=no

/system clock
set time-zone-autodetect=no
set time-zone-name="$timeZone"

:if ( ([:len $ntpServerIp1] > 0) and ([:len $ntpServerIp2] > 0) )  do={
  /system ntp client set enabled=yes primary-ntp="$ntpServerIp1" secondary-ntp="$ntpServerIp2"
} else={
  :if ([:len $ntpServerIp1] > 0) do={
    /system ntp client set enabled=yes primary-ntp="$ntpServerIp1"
    }
  }

:if ([:len $ntpServersFqdns] > 0) do={
  /system ntp client set enabled=yes server-dns-names="$ntpServersFqdns"
  }

:if ([:len $syslogServerIp] > 0) do={
  /system logging action add name=remoteSyslog remote="$syslogServerIp" target="remote"
  /system logging add action="remoteSyslog" topics="!dns"
  }

/system logging
add prefix="debug" topics="wireless"
add prefix="debug" topics="manager"

/interface bridge settings set allow-fast-path=yes use-ip-firewall=no use-ip-firewall-for-pppoe=no use-ip-firewall-for-vlan=no

:put ""
:put "========================================================================"
:put "=== Configuring bridges, vlan interfaces and associating them"
:put "========================================================================"

# Create bridges (associated to vlans)
:foreach vlanName,vlanId in=$vlanNamesConfig do={
  /interface bridge add name=("br-".$vlanName."-v".$vlanId)
  }

:if ($verboseConfig = "yes") do={ /interface bridge print brief }

# Create vlan interfaces
:foreach vlanName,vlanId in=$vlanNamesConfig do={
  :foreach iface in=($egressPortsToTagArray->$vlanId) do={
    /interface vlan add interface=$iface name=("vlif-".$vlanName."-".$iface."-v".$vlanId) vlan-id=$vlanId
    }
  }

:if ($verboseConfig = "yes") do={ /interface vlan print brief }

# Add vlan interfaces to the corresponding bridges
:foreach vlanName,vlanId in=$vlanNamesConfig do={
  :foreach iface in=($egressPortsToTagArray->$vlanId) do={
    #:put ("br-".$vlanName."-v".$vlanId."   "."vlif-".$vlanName."-".$iface."-v".$vlanId)
    /interface bridge port add bridge=("br-".$vlanName."-v".$vlanId) interface=("vlif-".$vlanName."-".$iface."-v".$vlanId)
    }
  }

:if ($verboseConfig = "yes") do={ /interface bridge port print brief }

# Add untagged ports to corresponding bridges
:foreach vlanName,vlanId in=$vlanNamesConfig do={
  :foreach iface in=([:toarray ($ingressPortsToTagArray->$vlanId)]) do={
    #:put ("br-".$vlanName."-v".$vlanId."  ".$iface)
    /interface bridge port add bridge=("br-".$vlanName."-v".$vlanId) interface=$iface
    }
  }

:if ($verboseConfig = "yes") do={ /interface bridge port print }

# Do not allow discovery
/ip neighbor discovery set discover-interface-list=none



:put ""
:put "======================================================================"
:put "= Configuring IP addresses and default route"
:put "======================================================================"

:foreach vlanName,ipAdressAndMaskSize in=$bridgesIps do={
  :if ([:len $ipAdressAndMaskSize] > 0) do={
    /ip address add address="$ipAdressAndMaskSize" interface=("br-".$vlanName."-v".($vlanNamesConfig->$vlanName))
    }
  }

:if ($verboseConfig = "yes") do={ /ip address print }

:if ([:len $defaultGw] > 0) do={
    /ip route add distance=1 gateway="$defaultGw"
    }

:if ($verboseConfig = "yes") do={ /ip route print }


:put ""
:put "======================================================================"
:put "= Configuring masquerading"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall nat
  add action=masquerade chain=srcnat log=yes log-prefix=out_masq out-interface=$internetBridgeNameConfig
  }



:put ""
:put "======================================================================"
:put "= Configuring adress-lists"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall address-list
  add address="$authorizedAdminNetwork" comment="Allowed IPs for this equipment managment " list=support

  add address=0.0.0.0/8 comment="Self-Identification [RFC 3330]" list=bogons
  add address=10.0.0.0/8 comment="Private[RFC 1918] - CLASS A # Check if you need this subnet before enable it" disabled=yes list=bogons
  add address=127.0.0.0/16 comment="Loopback [RFC 3330]" list=bogons
  add address=169.254.0.0/16 comment="Link Local [RFC 3330]" list=bogons
  add address=172.16.0.0/12 comment="Private[RFC 1918] - CLASS B # Check if you need this subnet before enable it" disabled=yes list=bogons
  add address=192.168.0.0/16 comment="Private[RFC 1918] - CLASS C # Check if you\_need this subnet before enable it" disabled=yes list=bogons
  add address=192.0.2.0/24 comment="Reserved - IANA - TestNet1" list=bogons
  add address=192.88.99.0/24 comment="6to4 Relay Anycast [RFC 3068]" list=bogons
  add address=198.18.0.0/15 comment="NIDB Testing" list=bogons
  add address=198.51.100.0/24 comment="Reserved - IANA - TestNet2" list=bogons
  add address=203.0.113.0/24 comment="Reserved - IANA - TestNet3" list=bogons
  add address=224.0.0.0/4 comment="MC, Class D, IANA # Check if you need this subnet before enable it" list=bogons

  /ip firewall address-list
  add address=0.0.0.0/8 comment=RFC6890 list=NotPublic
  add address=10.0.0.0/8 comment=RFC6890 list=NotPublic
  add address=100.64.0.0/10 comment=RFC6890 list=NotPublic
  add address=127.0.0.0/8 comment=RFC6890 list=NotPublic
  add address=169.254.0.0/16 comment=RFC6890 list=NotPublic
  add address=172.16.0.0/12 comment=RFC6890 list=NotPublic
  add address=192.0.0.0/24 comment=RFC6890 list=NotPublic
  add address=192.0.2.0/24 comment=RFC6890 list=NotPublic
  add address=192.168.0.0/16 comment=RFC6890 list=NotPublic
  add address=192.88.99.0/24 comment=RFC3068 list=NotPublic
  add address=198.18.0.0/15 comment=RFC6890 list=NotPublic
  add address=198.51.100.0/24 comment=RFC6890 list=NotPublic
  add address=203.0.113.0/24 comment=RFC6890 list=NotPublic
  add address=224.0.0.0/4 comment=RFC4601 list=NotPublic
  add address=240.0.0.0/4 comment=RFC6890 list=NotPublic
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : invalid packets dropping"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=separator comment="################################ DROP INVALID PACKETS"
  add action=drop chain=input comment="Drop input invalid packets" connection-state=invalid log=yes
  add action=drop chain=output comment="Drop output invalid packets" connection-state=invalid log=yes
  add action=drop chain=forward comment="Drop forward invalid packets" connection-state=invalid log=yes
  }


:put ""
:put "======================================================================"
:put "= Configuring firewall rules : attacks mitigation"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=comment comment="################################ ATTACKs MITIGATION"

  add chain=forward action=drop dst-address-list=bogons comment="Drop to bogon list"
  add action=drop chain=input comment="Drop all packets from public internet which should not exist in public network - input" in-interface="$internetBridgeNameConfig" src-address-list=NotPublic disabled=yes
  add action=drop chain=forward comment="Drop all packets from public internet which should not exist in public network -forward" in-interface="$internetBridgeNameConfig" dst-address-list=NotPublic disabled=yes
  add action=drop chain=output comment="Drop all packets to public internet which should not exist in public network - output" out-interface="$internetBridgeNameConfig" src-address-list=NotPublic disabled=yes

  add chain=input action=drop src-address-list=Port_Scanner comment="Drop to port scan list"
  add chain=forward action=drop dst-port=25,587 protocol=tcp src-address-list=spammers comment="Drop spammers"
  add chain=input action=drop protocol=tcp dst-port=22 src-address-list=ssh_blacklist comment="Drop ssh brute forcers" disabled=no
  add chain=input action=drop protocol=tcp dst-port=3389 src-address-list=rdp_blacklist comment="Drop RDP brute forcers" disabled=no
  add chain=input action=drop protocol=tcp dst-port=443 src-address-list=https_blacklist comment="Drop https brute forcers" disabled=no

  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp psd=21,3s,3,1 address-list-timeout=2w comment="Port scanners" disabled=no
  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp tcp-flags=fin,!syn,!rst,!psh,!ack,!urg address-list-timeout=2w comment="NMAP FIN Stealth scan"
  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp tcp-flags=fin,syn address-list-timeout=2w comment="SYN/FIN scan"
  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp tcp-flags=syn,rst address-list-timeout=2w comment="SYN/RST scan"
  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp tcp-flags=fin,psh,urg,!syn,!rst,!ack address-list-timeout=2w comment="FIN/PSH/URG scan"
  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp tcp-flags=fin,syn,rst,psh,ack,urg address-list-timeout=2w comment="ALL/ALL scan"
  add chain=input action=add-src-to-address-list address-list="Port_Scanner" protocol=tcp tcp-flags=!fin,!syn,!rst,!psh,!ack,!urg address-list-timeout=2w comment="NMAP NULL scan"

  add chain=forward action=add-src-to-address-list address-list=spammers address-list-timeout=3h connection-state=new connection-limit=30,32 dst-port=25,587 limit=30/1m,0:packet protocol=tcp comment="Add Spammers to the list for 3 hours"

  add chain=input action=add-src-to-address-list address-list=ssh_blacklist protocol=tcp dst-port=22 connection-state=new src-address-list=ssh_stage3 address-list-timeout=1d comment="Add SSH brute forcer to ssh_blacklist list" disabled=no
  add chain=input action=add-src-to-address-list address-list=ssh_stage3 protocol=tcp dst-port=22 connection-state=new src-address-list=ssh_stage2 address-list-timeout=1m comment="Add SSH brute forcer to ssh_stage3 list" disabled=no
  add chain=input action=add-src-to-address-list address-list=ssh_stage2 protocol=tcp dst-port=22 connection-state=new src-address-list=ssh_stage1 address-list-timeout=1m comment="Add SSH brute forcer to ssh_stage2 list" disabled=no
  add chain=input action=add-src-to-address-list address-list=ssh_stage1 protocol=tcp dst-port=22 connection-state=new address-list-timeout=1m comment="Add SSH brute forcer to ssh_stage1 list" disabled=no

  add chain=input action=add-src-to-address-list address-list=rdp_blacklist protocol=tcp dst-port=3389 connection-state=new src-address-list=rdp_stage4 address-list-timeout=1d comment="Add RDP brute forcer to rdp_blacklist list" disabled=no
  add chain=input action=add-src-to-address-list address-list=rdp_stage4 protocol=tcp dst-port=3389 connection-state=new src-address-list=rdp_stage3 address-list-timeout=1m comment="Add RDP brute forcer to rdp_stage4 list" disabled=no
  add chain=input action=add-src-to-address-list address-list=rdp_stage3 protocol=tcp dst-port=3389 connection-state=new src-address-list=rdp_stage2 address-list-timeout=1m comment="Add RDP brute forcer to rdp_stage3 list" disabled=no
  add chain=input action=add-src-to-address-list address-list=rdp_stage2 protocol=tcp dst-port=3389 connection-state=new src-address-list=rdp_stage1 address-list-timeout=1m comment="Add RDP brute forcer to rdp_stage2 list" disabled=no
  add chain=input action=add-src-to-address-list address-list=rdp_stage1 protocol=tcp dst-port=3389 connection-state=new address-list-timeout=1m comment="Add RDP brute forcer to rdp_stage1 list" disabled=no

  add chain=input action=add-src-to-address-list address-list=https_blacklist address-list-timeout=1h connection-state=new connection-limit=30,32 dst-port=443 limit=5/1m,0:packet protocol=tcp comment="Add HTTPS brute forcer to https_blacklist list"
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : established/related"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=comment comment="################################ ESTABLISHED / RELATED"
  add chain=input comment="Accept established/related connections/packets" connection-state=established,related
  add chain=forward comment="Accept established/related connections/packets" connection-state=established,related
  add chain=output comment="Accept established/related connections/packets" connection-state=established,related
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : input"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=comment comment="################################ INPUT"
  add action=drop chain=input comment="Drop all access to FW admin - except to support list" dst-port=21,22,23,80,443,8291,8728,8729 protocol=tcp src-address-list=!support

  add action=drop chain=input comment="Drop MT Discovery Protocol" dst-port=5678 protocol=udp
  add action=accept chain=input comment="Allow full access to SUPPORT address list" log-prefix=support-access src-address-list=support
  add action=accept chain=input comment="Allow localhost traffic" dst-address=127.0.0.1 src-address=127.0.0.1
  add action=accept chain=input comment="Allow Broadcast Traffic" dst-address-type=broadcast
  add action=accept chain=input comment="Allow UPnP udp/1900" dst-port=1900 protocol=udp disabled=yes
  add action=accept chain=input comment="Allow UPnP tcp/2828" dst-port=2828 protocol=tcp disabled=yes
  add action=accept chain=input comment="Allow SNMP requests from support tcp/161" dst-port=161 protocol=tcp src-address-list=support
  add action=accept chain=input comment="Allow SNMP requests from support udp/161" dst-port=161 protocol=udp src-address-list=support

  add action=accept chain=input comment="Allow DHCP requests from clients" src-port=68 dst-port=67 in-interface="!$internetBridgeNameConfig" protocol=udp
  add action=accept chain=input comment="Allow DHCP answers from others" src-port=67 dst-port=68 in-interface="!$internetBridgeNameConfig" protocol=udp
  add action=accept chain=input comment="Allow DNS requests from clients udp/53" dst-port=53 protocol=udp in-interface="!$internetBridgeNameConfig"
  add action=accept chain=input comment="Allow DNS requests from clients tcp/53" dst-port=53 protocol=tcp in-interface="!$internetBridgeNameConfig"
  add action=accept chain=input comment="Allow NTP requests from clients" dst-port=123 protocol=udp in-interface="!$internetBridgeNameConfig"
  add action=accept chain=input comment="Allow Web Proxy requests from clients" dst-port=8080 protocol=tcp disabled=yes
  add action=accept chain=input comment="Allow Socks requests from clients for Hotspot" dst-port=1080 protocol=tcp disabled=yes
  add action=accept chain=input comment="AllowBandwidth server requests from clients" dst-port=2000 protocol=tcp disabled=yes

  add action=accept chain=input comment="Allow PPTP connections from clients (tcp/1723)" dst-port=1723 protocol=tcp disabled=yes
  add action=accept chain=input comment="Allow PPTP and EoIP connections from clients (gre)" protocol=gre disabled=yes
  add action=accept chain=input comment="Allow IPIP connections from clients" protocol=ipencap disabled=yes
  add action=accept chain=input comment="Allow IPSec connections from clients (IKE)" dst-port=500 protocol=udp disabled=yes
  add action=accept chain=input comment="Allow IPSec connections from clients (ESP)" protocol=ipsec-esp disabled=yes
  add action=accept chain=input comment="Allow IPSec connections from clients (AH)" protocol=ipsec-ah disabled=yes
  add action=accept chain=input comment="Allow OpenVPN connections from clients tcp/1194" dst-port=1194 protocol=tcp disabled=yes
  add action=accept chain=input comment="Allow OpenVPN connections from clients udp/1194" dst-port=1194 protocol=udp disabled=yes

  add action=accept chain=input comment="Allow RIP connections from others" dst-port=520-521 protocol=udp disabled=yes
  add action=accept chain=input comment="Allow OSPF connections from others" protocol=ospf disabled=yes
  add action=accept chain=input comment="Allow BGP connections from others" dst-port=179 protocol=tcp disabled=yes
  add action=accept chain=input comment="Allow BGP connections from others" dst-port=5000-5100 protocol=udp disabled=yes

  add action=jump chain=input comment="Jump for icmp input flow" jump-target=ICMP protocol=icmp
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : output"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=comment comment="################################ OUTPUT"
  add action=accept chain=output comment="Allow localhost traffic" dst-address=127.0.0.1 src-address=127.0.0.1
  add action=accept chain=output comment="Allow Broadcast Traffic" dst-address-type=broadcast
  add action=accept chain=output comment="Allow UPnP udp/1900" dst-port=1900 protocol=udp disabled=yes
  add action=accept chain=output comment="Allow UPnP tcp/2828" dst-port=2828 protocol=tcp disabled=yes
  add action=accept chain=output comment="Allow SNMP traps outgoing tcp/162" dst-port=162 protocol=tcp dst-address-list=support
  add action=accept chain=output comment="Allow SNMP traps outgoing udp/162" dst-port=162 protocol=udp dst-address-list=support

  add action=accept chain=output comment="Allow DHCP requests from firewall" src-port=68 dst-port=67 protocol=udp
  add action=accept chain=output comment="Allow DHCP answers from firewall" src-port=67 dst-port=68 protocol=udp
  add action=accept chain=output comment="Allow DNS requests from firewall udp/53" dst-port=53 protocol=udp
  add action=accept chain=output comment="Allow DNS requests from firewall tcp/53" dst-port=53 protocol=tcp
  add action=accept chain=output comment="Allow NTP requests from firewall" dst-port=123 protocol=udp

  add action=accept chain=output comment="Allow WEB requests from firewall" dst-port=80,8080,443 protocol=tcp
  :if ([:len $syslogServerIp] > 0) do={
    add action=accept chain=output comment="Allow Syslog sending to syslog server tcp/514" dst-address="$syslogServerIp" dst-port=514 protocol=tcp
    add action=accept chain=output comment="Allow Syslog sending to syslog server udp/514" dst-address="$syslogServerIp" dst-port=514 protocol=udp
    }

  add action=accept chain=output comment="Allow PPTP connections from firewall (tcp/1723)" dst-port=1723 protocol=tcp disabled=yes
  add action=accept chain=output comment="Allow PPTP and EoIP connections from firewall (gre)" protocol=gre disabled=yes
  add action=accept chain=output comment="Allow IPIP connections from firewall" protocol=ipencap disabled=yes
  add action=accept chain=output comment="Allow IPSec connections from firewall (IKE)" dst-port=500 protocol=udp disabled=yes
  add action=accept chain=output comment="Allow IPSec connections from firewall (ESP)" protocol=ipsec-esp disabled=yes
  add action=accept chain=output comment="Allow IPSec connections from firewall (AH)" protocol=ipsec-ah disabled=yes
  add action=accept chain=output comment="Allow OpenVPN connections from firewall tcp/1194" dst-port=1194 protocol=tcp disabled=yes
  add action=accept chain=output comment="Allow OpenVPN connections from firewall udp/1194" dst-port=1194 protocol=udp disabled=yes

  add action=accept chain=output comment="Allow RIP connections to others" dst-port=520-521 protocol=udp disabled=yes
  add action=accept chain=output comment="Allow OSPF connections to others" protocol=ospf disabled=yes
  add action=accept chain=output comment="Allow BGP connections to others" dst-port=179 protocol=tcp disabled=yes
  add action=accept chain=output comment="Allow BGP connections to others" dst-port=5000-5100 protocol=udp disabled=yes

  add action=jump chain=output comment="Jump for icmp output" jump-target=ICMP protocol=icmp
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : forward"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=separator comment="################################ FORWARD"
  add action=drop chain=forward comment="Drop uTorrent" dst-port=53658 protocol=tcp  disabled=yes
  add action=drop chain=forward comment="Drop DC++ tcp/13336" dst-port=13336 protocol=tcp disabled=yes
  add action=drop chain=forward comment="Drop DC++ tcp/19030" dst-port=19030 protocol=tcp disabled=yes
  add action=drop chain=forward comment="Drop DC++ udp/12620" dst-port=12620 protocol=udp  disabled=yes
  add action=jump chain=forward comment="Jump for icmp forward flow" jump-target=ICMP protocol=icmp
  add chain=forward comment="Accept Internet outgoing" out-interface="$internetBridgeNameConfig"
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : ICMP chain"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=comment comment="################################ ICMP"
  add action=accept chain=ICMP comment="Echo request - Avoiding Ping Flood" icmp-options=8:0 limit=1,5:packet protocol=icmp
  add action=accept chain=ICMP comment="Echo reply" icmp-options=0:0 protocol=icmp
  add action=accept chain=ICMP comment="Time Exceeded" icmp-options=11:0 protocol=icmp
  add action=accept chain=ICMP comment="Destination unreachable" icmp-options=3:0-1 protocol=icmp
  add action=accept chain=ICMP comment=PMTUD icmp-options=3:4 protocol=icmp
  add action=drop chain=ICMP comment="Drop to the other ICMPs" protocol=icmp
  }



:put ""
:put "======================================================================"
:put "= Configuring firewall rules : final rejects/drops"
:put "======================================================================"

:if ($functionnalModeConfig = "firewall" ) do={
  /ip firewall filter
  add action=passthrough chain=comment comment="################################ FINAL REJECT / DROP"
  add action=reject chain=input in-interface="!$internetBridgeNameConfig" log=yes log-prefix=reject:input reject-with=icmp-admin-prohibited
  add action=reject chain=forward in-interface="!$internetBridgeNameConfig" log=yes log-prefix=reject:forward reject-with=icmp-admin-prohibited
  add action=reject chain=output log=yes log-prefix=reject:output out-interface="!$internetBridgeNameConfig" reject-with=icmp-admin-prohibited
  add action=drop chain=input log=yes log-prefix=drop:input
  add action=drop chain=forward log=yes log-prefix=drop:forward
  add action=drop chain=output log=yes log-prefix=drop:output
  }


:put ""
:put "======================================================================"
:put " = HTTPS certificate generation (takes some time...)"
:put "======================================================================"

/certificate
add name="catmpl-$localHostname" common-name="ca-$localHostname" key-usage=key-cert-sign,crl-sign days-valid=10000 key-size=4096
add name="fwtmpl-$localHostname" common-name="$localFqdn"  days-valid=10000 key-size=4096
sign "catmpl-$localHostname" ca-crl-host=127.0.0.1 name="ca-$localHostname"
:delay 1s
sign ca="ca-$localHostname" "fwtmpl-$localHostname" name="$localHostname"
:delay 1s
set "ca-$localHostname" trusted=yes
set "$localHostname" trusted=yes
export-certificate "ca-$localHostname"
/ip service set www-ssl certificate="$localHostname" disabled=no

# Wait for certificates to be created
  {
  :local count 0;
  :while ([/certificate find where name="$localHostname"] = "") do={
    :if ($count = 30) do={
      /quit;
      }
    :delay 1s; :set count ($count +1);
    };
  }



:put ""
:put "========================================================================"
:put "=== Destroying defined global variables"
:put "========================================================================"

:set vlanNamesConfig
:set bridgesIps
:set adminVlanNameConfig
:set internetVlanNameConfig
:set internetBridgeNameConfig
:set vlansConfig
:set functionnalModeConfig
:set verboseConfig
:set keyInSimpleArray
:set keyInArray
:set vlanNameArray
:set localEthernetInterfaces
:set egressPortsToTagArray
:set ingressPortsToTagArray
:set configurationOk
:set administrationIp
:set defaultGw
:set localHostname
:set localFqdn
:set dnsServers
:set timeZone
:set ntpServerIp1
:set ntpServerIp2
:set ntpServersFqdns
:set syslogServerIp
:set adminUserName
:set adminPassword
:set authorizedAdminNetwork



:put ""
:put "========================================================================"
:put "=== End of script noise"
:put "========================================================================"

 :for i from=500 to=10000 step=500 do={
   :beep frequency=$i length=11ms;
   :delay 11ms;
 }
 :delay 50ms;
 :for i from=500 to=10000 step=500 do={
   :beep frequency=$i length=11ms;
   :delay 11ms;
 }
 :delay 50ms;
 :for i from=500 to=10000 step=500 do={
   :beep frequency=$i length=11ms;
   :delay 11ms;
 }

 
ghusson
just joined
Topic Author
Posts: 5
Joined: Thu Mar 01, 2018 11:41 am

Re: Staging script example

Fri Aug 24, 2018 3:32 pm

Next updates will be available here : https://www.liberasys.com/wiki/doku.php ... te_staging
Please tell it if it is usefull for you :-)

Who is online

Users browsing this forum: No registered users and 10 guests