# ====== 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 : change admin name, not working anymore
#TODO : debug 2048bits certificate generation, not working anymore
#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 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 "firewall"

# /!\  !!! 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 {
    "admin-admin"="1";
    "admin-capsman"="10";
    "pro-dmz"="20";
    "pro-voip"="30";
    "pro-vidsurv"="40";
    "pro-lan"="50";
    "pro-wifi"="55";
    "pro-vpn-site"="60";
    "pro-vpn-user-managed"="65";
    "fournisseurs-dmz"="150";
    "pro-invite"="170";
    "guest-wifi"="190";
    "pro-vpn-user-unmanaged"="210";
    "fai1"="230";
    }

:global adminVlanNameConfig "admin-admin"
:global internetVlanNameConfig "fai1"


# Ips on bridges :
:global bridgesIps {
                   "admin-admin"="10.1.1.254/24";
                   "pro-lan"="192.168.1.1/24";
                   "pro-vpn-user-managed"="10.1.65.254/24";
                   "pro-vpn-user-unmanaged"="10.1.210.254/24";
                   "fai1"="10.1.230.253/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={"pro-lan";};};
                    ether2={mode="untagged"; vlans={"pro-lan";};};
                    ether3={mode="untagged"; vlans={"pro-lan";};};
                    ether4={mode="untagged"; vlans={"admin-admin";};};
                    ether5={mode="untagged"; vlans={"fai1";};};
#                    ether6={mode="untagged"; vlans={"pro-lan";};};
#                    ether7={mode="untagged"; vlans={"pro-lan";};};
#                    ether8={mode="untagged"; vlans={"pro-lan";};};
#                    ether9={mode="untagged"; vlans={"pro-lan";};};
#                    ether10={mode="untagged"; vlans={"pro-lan";};};
#                    ether11={mode="untagged"; vlans={"pro-lan";};};
#                    ether12={mode="untagged"; vlans={"pro-lan";};};
#                    ether13={mode="untagged"; vlans={"pro-lan";};};
#                    ether14={mode="untagged"; vlans={"pro-lan";};};
#                    ether15={mode="untagged"; vlans={"pro-lan";};};
#                    ether16={mode="untagged"; vlans={"pro-lan";};};
#                    ether17={mode="untagged"; vlans={"pro-lan";};};
#                    ether18={mode="untagged"; vlans={"pro-lan";};};
#                    ether19={mode="untagged"; vlans={"pro-lan";};};
#                    ether20={mode="untagged"; vlans={"pro-lan";};};
#                    ether21={mode="trunk"; vlans={"pro-lan"; "fai1"};};
#                    ether22={mode="tagged";vlans={"fai1"};};
#                    ether23={mode="untagged"; vlans={"fai1";};};
#                    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 "test-staging.liberasys.com";
:global timeZone "Europe/Paris"
:global authorizedAdminNetwork "10.1.1.0/24"
:global defaultGw "10.1.230.254"
:global dnsServers "10.1.230.254,8.8.8.8"
: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 "10.1.1.200"
:global sshPortMikrotik "42022"
:global httpsPortMikrotik "42443"
:global sstpPortMikrotik "42444"

# 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 Admin bridge name
:global adminBridgeNameConfig
:set adminBridgeNameConfig
:global adminBridgeNameConfig
:set adminBridgeNameConfig ("br-".$adminVlanNameConfig."-v".($vlanNamesConfig->$adminVlanNameConfig))


# 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 ($vlansConfig->$iface->"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={}
    }
  }

# 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="!debug,!packet"] } on-error={}
:do { /system logging remove [/system logging find where action="remoteSyslog" and topics="dhcp"] } on-error={}
:do { /system logging remove [/system logging find where action="remoteSyslog" and topics="account"] } 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 remove [/system logging find where topics="account"] } 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 add name=$"adminUserName" group=full password="$adminPassword" disabled=no
/user remove admin

: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=yes
/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"
set ssh port="$sshPortMikrotik"
set www-ssl port="$httpsPortMikrotik"
: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 servers="$ntpServerIp1,$ntpServerIp2"
} else={
  :if ([:len $ntpServerIp1] > 0) do={
    /system ntp client set enabled=yes servers="$ntpServerIp1"
    }
  }

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


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

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

/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=10.0.0.0/8 comment="CLASS A - Private[RFC 1918] ### Check if you need this subnet before enable it" disabled=yes list=bogons
  add address=172.16.0.0/12 comment="CLASS B - Private[RFC 1918] ### Check if you need this subnet before enable it" disabled=yes list=bogons
  add address=192.168.0.0/16 comment="CLASS C - Private[RFC 1918] ### Check if you need this subnet before enable it" disabled=yes list=bogons
  add address=224.0.0.0/4 comment="CLASS D / MULTICAST IANA ### Check if you need this subnet before enable it" list=bogons

  add address=0.0.0.0/8 comment="Self-Identification [RFC 3330]" list=bogons
  add address=127.0.0.0/16 comment="Loopback [RFC 3330]" list=bogons
  add address=100.64.0.0/10 comment="RFC6890" list=bogons
  add address=169.254.0.0/16 comment="Link Local [RFC 3330]" list=bogons
  add address=192.0.0.0/24 comment="RFC6890" 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=240.0.0.0/4 comment="RFC6890" list=bogons
  }


: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 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,$sshPortMikrotik" 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,$httpsPortMikrotik" 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,$sshPortMikrotik" 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,$sshPortMikrotik" 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,$sshPortMikrotik" 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,$sshPortMikrotik" 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,$httpsPortMikrotik" 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,$sshPortMikrotik,23,80,443,$httpsPortMikrotik,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="EXAMPLE Allow CAPs to reach CAPsMAN" dst-port=5246,5247 in-interface=$adminBridgeNameConfig log=yes log-prefix=capsman-in protocol=udp disabled=yes
  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 (IKE2/nat traversal)" 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 SSTP connections from clients tcp/$sstpPortMikrotik" dst-port="$sstpPortMikrotik" protocol=tcp 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 Mikrotik Cloud Traffic" dst-port=15252 protocol=udp
  add action=accept chain=output comment="EXAMPLE Allow CAPsMAN to reach CAPs" log=yes log-prefix=capsman-out out-interface=$adminBridgeNameConfig protocol=udp src-port=5246,5247 disabled=yes
  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 (IKE2/nat traversal)" dst-port=4500 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 SSTP connections from firewall tcp/$sstpPortMikrotik" dst-port="$sstpPortMikrotik" protocol=tcp 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 adminBridgeNameConfig
: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
:set sshPortMikrotik
:set httpsPortMikrotik
:set sstpPortMikrotik


:put "========================================================================"
:put "=== Some usefull scripts"
:put "========================================================================"

/system script
add name=backup_script owner=creadmin source=":local curDate [/system clock get date]\
    \n:local curTime [/system clock get time]\
    \n:local systemName [/system identity get name]\
    \n:local curMonth [:pick \$curDate 0 3]\
    \n :set curMonth ( [ :find key=\"\$curMonth\" in=\"jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec\" from=-1 ] / 4 + 1)\
    \n if ( \$curMonth < 10 ) do={\
    \n  :set curMonth ( \"0\".\$curMonth )\
    \n } else={\
    \n  :set curMonth \$curMonth\
    \n }\
    \n:local curDay   [:pick \$curDate 4 6]\
    \n:local curYear  [:pick \$curDate 7 13]\
    \n:local curHour  [:pick \$curTime 0 2]\
    \n:local curMin   [:pick \$curTime 3 5]\
    \n\
    \n/\
    \n/export show-sensitive file=( \"\$systemName\".\"-\".\"\$curYear\".\"\$curMonth\".\"\$curDay\" .\"-\".\"\$curHour\".\"\$curMin\" )\
    \n/file print"



: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;
 }



:put "======================================================================"
:put "======================================================================"
:put "======================================================================"
:put "====MANUAL ADDING FOR EXAMPLES ======================================="
:put "======================================================================"
:put "======================================================================"
:put "======================================================================"



/ip pool
add name=dhcpp-admin-admin ranges=10.1.1.101-10.1.1.199
add name=dhcpp-pro-lan ranges=192.168.1.101-192.168.1.199
add name=dhcpp-pro-lan-vpn-user-inside_lan ranges=192.168.1.51-192.168.1.99
add name=dhcpp-vpn-user-managed ranges=10.1.65.101-10.1.65.199
add name=dhcpp-vpn-user-unmanaged ranges=10.1.210.101-10.1.210.199

/ip dhcp-server
add address-pool=dhcpp-admin-admin disabled=no interface=br-admin-admin-v1 name=dhcps-admin-admin
add address-pool=dhcpp-pro-lan disabled=no interface=br-pro-lan-v50 name=dhcps-pro-lan

/ip dhcp-server network
add address=10.1.1.0/24 dns-server=10.1.1.254 gateway=10.1.1.254
add address=192.168.1.0/24 dns-server=192.168.1.1 gateway=192.168.1.1

/ip firewall address-list
add address=1.2.3.4 comment="Robert VAL - XTRACmpy - home" list=support
add address=192.168.1.0/24 comment="Local Admin via pro-lan" list=support

/interface wireless disable wlan1
/interface wireless disable wlan2

# !!! Go to DHCP client to FAI interface !
#ip address disable [find where address="10.1.230.253/24"]
#/ip dhcp-client add interface=br-fai1-v230 disabled=no

/ip cloud force-update
:delay 10s
/ip cloud print
/system clock print
/ip firewall filter enable [find where comment="Allow SSTP connections from clients tcp/42444"]



:put ""
:put "======================================================================"
:put " = Set variables for SSTP script "
:put "======================================================================"
/
:global sstpPortMikrotik "42444"

:global lanBridge "br-pro-lan-v50"
:global lanBridgeIp "192.168.1.1"
:global lanDnsServer "192.168.1.1"
:global lanUserIpPool "dhcpp-pro-lan-vpn-user-inside_lan"

:global managedUserBridge "br-pro-vpn-user-managed-v65"
:global managedUserBridgeIp "10.1.65.254"
:global managedUserDnsServer "10.1.65.254"
:global managedUserIpPool "dhcpp-vpn-user-managed"

:global notManagedUserBridge "br-pro-vpn-user-unmanaged-v210"
:global notManagedUserBridgeIp "10.1.210.254"
:global notManagedUserDnsServer "10.1.210.254"
:global notManagedUserIpPool "dhcpp-vpn-user-unmanaged"

:global initialUserName "ghusson"
:global initialUserPassword "ghusson.1"

:global wanIp [/ip cloud get public-address];
:global ddnsName [/ip cloud get dns-name];
/env print

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

/certificate
add name="sstpcatmpl-$ddnsName" common-name="ca-$ddnsName" key-usage=key-cert-sign,crl-sign days-valid=10000 key-size=2048
add name="sstpclitmpl-$ddnsName" common-name="$ddnsName"  days-valid=10000 key-size=2048
sign "sstpcatmpl-$ddnsName" ca-crl-host="" name="ca-$ddnsName"
:delay 1s
sign ca="ca-$ddnsName" "sstpclitmpl-$ddnsName" name="$ddnsName"
:delay 1s
set "ca-$ddnsName" trusted=yes
set "$ddnsName" trusted=yes
export-certificate "ca-$ddnsName"

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


:put ""
:put "======================================================================"
:put " = Enable SSTP server, add initial user profile and enable proxy-arp "
:put "======================================================================"

/interface list add name=iflist_sstp_inside_lan
/interface list add name=iflist_sstp_managed
/interface list add name=iflist_sstp_unmanaged

# VPN users directly in LAN (trusted, or admins) : inside lan
/ppp profile add bridge="$lanBridge" change-tcp-mss=yes comment="SSTP VPN Profile for clients inside pro lan"\
  dns-server="$lanDnsServer" local-address="$lanBridgeIp" name=ppp_profile_sstp_inside_lan only-one=yes\
  remote-address="$lanUserIpPool" use-compression=yes use-encryption=yes use-mpls=no use-upnp=no interface-list=iflist_sstp_inside_lan

# VPN users that have customer managed equipment : managed
/ppp profile add bridge="$managedUserBridge" change-tcp-mss=yes comment="SSTP VPN Profile for managed clients"\
  dns-server="$managedUserDnsServer" local-address="$managedUserBridgeIp" name=ppp_profile_sstp_managed only-one=yes\
  remote-address="$managedUserIpPool" use-compression=yes use-encryption=yes use-mpls=no use-upnp=no interface-list=iflist_sstp_managed

# VPN users that have personnal equipment : UNmanaged
/ppp profile add bridge="$notManagedUserBridge" change-tcp-mss=yes comment="SSTP VPN Profile for UNmanaged clients"\
  dns-server="$notManagedUserDnsServer" local-address="$notManagedUserBridgeIp" name=ppp_profile_sstp_unmanaged only-one=yes\
  remote-address="$notManagedUserIpPool" use-compression=yes use-encryption=yes use-mpls=no use-upnp=no interface-list=iflist_sstp_unmanaged

/interface sstp-server server set default-profile=ppp_profile_sstp_unmanaged
/interface sstp-server server set certificate="$ddnsName"
/interface sstp-server server set authentication=mschap2
/interface sstp-server server set port="$sstpPortMikrotik"
/interface sstp-server server set keepalive-timeout=60
/interface sstp-server server set enabled=yes

/ppp secret add name="$initialUserName" password="$initialUserPassword" service=sstp profile=ppp_profile_sstp_managed

/interface bridge set "$lanBridge" arp=proxy-arp
/interface bridge set "$managedUserBridge" arp=proxy-arp



:put ""
:put "======================================================================"
:put " = Create firewall rules "
:put "======================================================================"
/ip firewall filter

# sstp_inside_lan
add action=accept chain=forward comment="SSTP inside LAN -> LAN" in-interface-list=iflist_sstp_inside_lan out-interface="$lanBridge" log=yes log-prefix=sstpinlan disabled=no
add action=accept chain=forward comment="SSTP inside LAN -> inside LAN" in-interface-list=iflist_sstp_inside_lan out-interface-list=iflist_sstp_inside_lan log=yes log-prefix=sstpinlan disabled=no
add action=accept chain=forward comment="LAN -> inside LAN" in-interface="$lanBridge" out-interface-list=iflist_sstp_inside_lan log=yes log-prefix=sstpinlan disabled=no

# sstp_managed
add action=accept chain=forward comment="SSTP managed -> LAN" in-interface-list=iflist_sstp_managed out-interface="$lanBridge" log=yes log-prefix=sstpmngd disabled=no
add action=accept chain=forward comment="SSTP managed -> SSTP managed" in-interface-list=iflist_sstp_managed out-interface-list=iflist_sstp_managed log=yes log-prefix=sstpmngd disabled=yes
add action=accept chain=forward comment="LAN -> SSTP managed" in-interface="$lanBridge" out-interface-list=iflist_sstp_managed log=yes log-prefix=sstpmngd disabled=no

# sstp_unmanaged
add action=accept chain=forward comment="SSTP UNmanaged -> LAN" in-interface-list=iflist_sstp_unmanaged out-interface="$lanBridge" log=yes log-prefix=sstpunmngd disabled=no
add action=accept chain=forward comment="SSTP UNmanaged -> SSTP UNmanaged" in-interface-list=iflist_sstp_unmanaged out-interface-list=iflist_sstp_unmanaged log=yes log-prefix=sstpunmngd disabled=yes
add action=accept chain=forward comment="LAN -> SSTP UNmanaged" in-interface="$lanBridge" out-interface-list=iflist_sstp_unmanaged log=yes log-prefix=sstpunmngd disabled=yes




:put ""
:put "======================================================================"
:put " = Clean variables for SSTP script "
:put "======================================================================"
:set sstpPortMikrotik
:set managedUserDnsServer
:set managedUserBridgeIp
:set managedUserBridge
:set notManagedUserDnsServer
:set notManagedUserBridgeIp
:set notManagedUserBridge
:set initialUserName
:set initialUserPassword
:set managedUserIpPool
:set wanIp
:set ddnsName