RouterOS Howto (1) - Part 4
This is Part 4 of the RouterOS Howto for MikroTik hEX S.
Configure the Firewall
Documentation:
[RouterOS CLI]: Define ruleset version
:global rulesetVersion "v001"
:global ruleName "Dummy"
[RouterOS CLI]: Configure several IP related Kernel parameters
/ip/settings
    set ip-forward="yes" send-redirects="yes" accept-source-route="yes" \
        accept-redirects="no" secure-redirects="yes" rp-filter="strict" \
        tcp-syncookies="yes" allow-fast-path="no"
    print
[RouterOS CLI]: Disable all service ports except tftp
/ip/firewall/service-port
    enable "tftp"
    disable [find where name!="tftp"]
    print detail
Configure address lists
[RouterOS CLI]: Configure address lists for the internal network segments
/ip/firewall/address-list
    add list="lan-router" address="192.168.1.0/28"
    add list="lan-network" address="192.168.1.16/28"
    add list="lan-tools" address="192.168.1.32/28"
    add list="lan-server" address="192.168.1.48/28"
    add list="lan-kubernetes" address="192.168.1.64/28"
    add list="lan-client" address="192.168.1.128/28"
    add list="lan-multimedia" address="192.168.1.144/28"
    add list="lan-gaming" address="192.168.1.160/28"
    add list="lan-guest" address="192.168.1.240/28"
    print detail where list~"^lan"
[RouterOS CLI]: Configure an address list for Multicast
/ip/firewall/address-list
    add list="multicast" address="224.0.0.0/4"
    print detail where list="multicast"
[RouterOS CLI]: Configure an address list for bogons addresses
:global listName "bogons"
/ip/firewall/address-list
    add list="$listName" address="0.0.0.0/8"
    add list="$listName" address="192.168.1.0/8" disabled="yes"
    add list="$listName" address="100.64.0.0/10"
    add list="$listName" address="127.0.0.0/8"
    add list="$listName" address="169.254.0.0/16"
    add list="$listName" address="172.16.0.0/12"
    add list="$listName" address="192.0.0.0/24"
    add list="$listName" address="192.0.0.0/29"
    add list="$listName" address="192.0.2.0/24"
    add list="$listName" address="192.88.99.0/24"
    add list="$listName" address="192.168.0.0/16"
    add list="$listName" address="198.18.0.0/15"
    add list="$listName" address="198.51.100.0/24"
    add list="$listName" address="203.0.113.0/24"
    add list="$listName" address="224.0.0.0/4" disabled="yes"
    print detail where list="$listName"
Configure rules for known connections
[RouterOS CLI]: Configure rules for known connections
:global groupName "PRE"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :foreach chain in={"forward"; "output"; "input"} do={
        :global ruleName "Fasttrack"
        add chain="$chain" action="fasttrack-connection" \
            connection-state="established,related" \
            log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
        :global ruleName "State"
        add chain="$chain" action="accept" \
            connection-state="established,related" \
            log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    }
Configure rules for unwanted connections
[RouterOS CLI]: Configure rules for unwanted connections
:global groupName "PRE"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :foreach chain in={"forward"; "input"} do={
        :global ruleName "Drop invalid"
        add chain="$chain" action="drop" \
            connection-state="invalid,untracked" \
            log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
        :global ruleName "Drop Bogons"
        add chain="$chain" action="drop" \
            dst-address-list="bogons" \
            log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    }
WAN 2 FW connections
[RouterOS CLI]: Configure rules for connections from WAN to Firewall
:global chain "input"
:global inInterface "WAN"
:global groupName "$inInterface 2 FW"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :global ruleName "Drop"
    add chain="$chain" action="drop" \
        in-interface-list="$inInterface" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
WAN 2 LAN-STD connections
[RouterOS CLI]: Configure rules for connections from WAN to LAN-STD
:global chain "forward"
:global inInterface "WAN"
:global outInterface "LAN-STD"
:global groupName "$inInterface 2 $outInterface"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :global ruleName "Drop"
    add chain="$chain" action="drop" \
        in-interface-list="$inInterface" out-interface-list="$outInterface" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
WAN 2 LAN-STD-GW connections
[RouterOS CLI]: Configure rules for connections from WAN to LAN-STD-GW
:global chain "forward"
:global inInterface "WAN"
:global outInterface "LAN-STD-GW"
:global groupName "$inInterface 2 $outInterface"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :global ruleName "Drop"
    add chain="$chain" action="drop" \
        in-interface-list="$inInterface" out-interface-list="$outInterface" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
LAN-STD 2 WAN connections
[RouterOS CLI]: Configure rules for connections from LAN-STD-GW to WAN
:global chain "forward"
:global inInterface "LAN-STD"
:global outInterface "WAN"
:global groupName "$inInterface 2 $outInterface"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :global ruleName "Drop"
    add chain="$chain" action="drop" \
        in-interface-list="$inInterface" out-interface-list="$outInterface" \
        log="yes" log-prefix=[$getLogPrefix] comment=[$getComment]
LAN-STD-GW 2 WAN connections
[RouterOS CLI]: Configure IP masquerade from LAN-STD-GW to WAN
:global chain "srcnat"
:global inInterface "LAN-STD-GW"
:global outInterface "WAN"
:global groupName "$inInterface 2 $outInterface"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/nat
    :global ruleName "Masquerade"
    add chain="$chain" action="masquerade" \
        out-interface-list="$outInterface" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
| Src | Dst | Src Port | Dst Port | |
|---|---|---|---|---|
| TCP | any | SSH (22, 2121), SMTP (25), HTTP (80), HTTPS (443, 8443), Submission (587), IMAPS (993), HKP (11371) | ||
| lan-gaming | TCP | any | any | |
| UDP | any | IPsec (500,4500), OpenVPN (1194), Reolink (9999), WireGuard (51820) | ||
| lan-gaming | UDP | any | any | |
| ICMP | - | - | 
[RouterOS CLI]: Configure rules for connections from LAN-STD-GW to WAN
:global chain "forward"
:global inInterface "LAN-STD-GW"
:global outInterface "WAN"
:global groupName "$inInterface 2 $outInterface"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :global ruleName "TCP"
    add chain="$chain" action="accept" \
        in-interface-list="$inInterface" out-interface-list="$outInterface" \
        protocol="tcp" dst-port="22,25,80,443,587,993,2121,8443,11371" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "TCP Gaming"
    add chain="$chain" action="accept" \
        in-interface-list="$inInterface" out-interface-list="$outInterface" \
        src-address-list="lan-gaming" \
        protocol="tcp" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "UDP"
    add chain="$chain" action="accept" \
        in-interface-list="$inInterface" out-interface-list="$outInterface" \
        protocol="udp" dst-port="500,1194,4500,9999,51820" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "UDP Gaming"
    add chain="$chain" action="accept" \
        in-interface-list="$inInterface" out-interface-list="$outInterface" \
        src-address-list="lan-gaming" \
        protocol="udp" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "ICMP"
    add chain="$chain" action="accept" \
        in-interface-list="$inInterface" out-interface-list="$outInterface" \
        protocol="icmp" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "Drop"
    add chain="$chain" action="drop" \
        in-interface-list="$inInterface" out-interface-list="$outInterface" \
        log="yes" log-prefix=[$getLogPrefix] comment=[$getComment]
LAN-STD 2 FW connections
| Src | Dst | Src Port | Dst Port | |
|---|---|---|---|---|
| TCP | any | SSH (22), HTTP (80), HTTPS (443) | ||
| lan-router | multicast | VRRP | - | - | 
| ICMP | - | - | 
[RouterOS CLI]: Configure rules for connections from LAN-STD to Firewall
:global chain "input"
:global inInterface "LAN-STD"
:global groupName "$inInterface 2 FW"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :global ruleName "TCP"
    add chain="$chain" action="accept" \
        in-interface-list="$inInterface" \
        protocol="tcp" dst-port="22,80,443" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "VRRP"
    add chain="$chain" action="accept" \
        in-interface-list="$inInterface" \
        src-address-list="lan-router" dst-address-list="multicast" \
        protocol="vrrp" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "ICMP"
    add chain="$chain" action="accept" \
        in-interface-list="$inInterface" \
        protocol="icmp" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "Drop"
    add chain="$chain" action="drop" \
        in-interface-list="$inInterface" \
        log="yes" log-prefix=[$getLogPrefix] comment=[$getComment]
LAN-STD-GW 2 FW connections
| Src | Dst | Src Port | Dst Port | |
|---|---|---|---|---|
| TCP | any | DNS (53) | ||
| UDP | any | DNS (53), BOOTP (67), TFTP (69), NTP (123) | ||
| ICMP | - | - | 
[RouterOS CLI]: Configure rules for connections from LAN-STD-GW to Firewall
:global chain "input"
:global inInterface "LAN-STD-GW"
:global groupName "$inInterface 2 FW"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :global ruleName "TCP"
    add chain="$chain" action="accept" \
        in-interface-list="$inInterface" \
        protocol="tcp" dst-port="53" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "UDP"
    add chain="$chain" action="accept" \
        in-interface-list="$inInterface" \
        protocol="udp" dst-port="53,67,69,123" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "ICMP"
    add chain="$chain" action="accept" \
        in-interface-list="$inInterface" \
        protocol="icmp" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "Drop"
    add chain="$chain" action="drop" \
        in-interface-list="$inInterface" \
        log="yes" log-prefix=[$getLogPrefix] comment=[$getComment]
FW 2 LAN-STD connections
| Src | Dst | Src Port | Dst Port | |
|---|---|---|---|---|
| TCP | any | DNS (53), HTTP (80), HTTPS (443) | ||
| UDP | any | DNS (53), NTP (123) | ||
| ICMP | - | - | 
[RouterOS CLI]: Configuring rules for connections from Firewall to LAN-STD
:global chain "output"
:global outInterface "LAN-STD"
:global groupName "FW 2 $outInterface"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :global ruleName "TCP"
    add chain="$chain" action="accept" disabled="yes" \
        out-interface-list="$outInterface" \
        protocol="tcp" dst-port="53,80,443" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "UDP"
    add chain="$chain" action="accept" disabled="yes" \
        out-interface-list="$outInterface" \
        protocol="udp" dst-port="53,123" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "ICMP"
    add chain="$chain" action="accept" \
        out-interface-list="$outInterface" \
        protocol="icmp" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "Drop"
    add chain="$chain" action="drop" \
        out-interface-list="$outInterface" \
        log="yes" log-prefix=[$getLogPrefix] comment=[$getComment]
FW 2 LAN-STD-GW connections
[RouterOS CLI]: Configuring rules for connections from Firewall to LAN-STD-GW
:global chain "output"
:global outInterface "LAN-STD-GW"
:global groupName "FW 2 $outInterface"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :global ruleName "Drop"
    add chain="$chain" action="drop" \
        out-interface-list="$outInterface" \
        log="yes" log-prefix=[$getLogPrefix] comment=[$getComment]
FW 2 WAN connections
| Src | Dst | Src Port | Dst Port | |
|---|---|---|---|---|
| TCP | any | DNS (53), HTTP (80), HTTPS (443), Submission (587) | ||
| UDP | any | DNS (53), NTP (123), DDNS (15252) | ||
| ICMP | - | - | 
[RouterOS CLI]: Configure rules for connections from Firewall to WAN
:global chain "output"
:global outInterface "WAN"
:global groupName "FW 2 $outInterface"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :global ruleName "TCP"
    add chain="$chain" action="accept" \
        out-interface-list="$outInterface" \
        protocol="tcp" dst-port="53,80,443,587" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "UDP"
    add chain="$chain" action="accept" \
        out-interface-list="$outInterface" \
        protocol="udp" dst-port="53,123,15252" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "ICMP"
    add chain="$chain" action="accept" \
        out-interface-list="$outInterface" \
        protocol="icmp" \
        log="no" log-prefix=[$getLogPrefix] comment=[$getComment]
    :global ruleName "Drop"
    add chain="$chain" action="drop" \
        out-interface-list="$outInterface" \
        log="yes" log-prefix=[$getLogPrefix] comment=[$getComment]
Final Drop rules
[RouterOS CLI]: Configure final drop rules
:global groupName "POST"
:global ruleName "Drop any"
:global getLogPrefix do={ :return "$groupName ($ruleName)" }
:global getComment do={ :return "$groupName ($ruleName) $rulesetVersion" }
/ip/firewall/filter
    :foreach chain in={"forward"; "output"; "input"} do={
        add chain="$chain" action="drop" \
            log="yes" log-prefix=[$getLogPrefix] comment=[$getComment]
    }
Remove default rules
[RouterOS CLI]: Delete all rules that start with defconf or contain an old version number vXXX
:foreach table in={"filter"; "nat"} do={
    [:parse " \
        /ip/firewall/$table remove \
            [find comment~\"^defconf\" or comment~\"v001\"] \
    "]
}
Show all rules
[RouterOS CLI]: Show the rules from the chains filter & nat
:foreach table in={"filter"; "nat"} do={
    [:parse "/ip/firewall/$table print without-paging"]
}
Monitor the Firewall logs
[RouterOS CLI]: Monitor the Firewall logs
/log print follow where topics~"^firewall"
Reset all Firewall counters
[RouterOS CLI]: Reset the Firewall counters for the chains filter, nat, mangle & raw
:foreach table in={"filter"; "nat"; "mangle", "raw"} do={
    [:parse "/ip/firewall/$table reset-counters-all"]
}
Create Backups
Documentation:
[UNIX shell]: Define environment
- for tellurium.raysoft.loc
host_name='tellurium'
- for palladium.raysoft.loc
host_name='palladium'
[RouterOS CLI]: Create a backup & show the file
/system/backup/save dont-encrypt="yes"
/file print where type="backup"
[UNIX shell]: Download the backup file
scp "scp://admin@${host_name}.raysoft.loc/flash/${host_name}-DATE-COUNTER.backup" \
  "${HOME}/Documents/41-maschinen/${host_name}.raysoft.loc/backup"
[RouterOS CLI]: Remove all backup files
/file remove [find type="backup"]
Create Backups automatically
[UNIX shell]: Define environment
- for tellurium.raysoft.loc
host_name='tellurium'
- for palladium.raysoft.loc
host_name='palladium'
- all machines
host="admin@${host_name}.raysoft.loc"
[UNIX shell]: Create a backup remotely
ssh "${host}" '/system backup save dont-encrypt="yes"'
[UNIX shell]: Download all available backup files
while read -r file; do
  scp "scp://${host}/${file}" \
    "${HOME}/Documents/41-maschinen/${host##*@}/backup"
done < <(ssh "${host}" '/file print terse where type="backup"' \
         | sed '/^\s*$/d; s/.*name=\([^ ]*\).*/\1/')
[UNIX shell]: Remove all backup files remotely
ssh "${host}" '/file remove [find type="backup"]'