From 124cc3aa01ed0c45cf5fdce6120f74e44e66bf3c Mon Sep 17 00:00:00 2001 From: Max O'Cull Date: Tue, 17 Sep 2024 03:10:41 -0400 Subject: [PATCH] Add mikrotik firewall scripts --- .zshrc | 15 ++ scripts/mikrotik/README.md | 3 + scripts/mikrotik/firewall.rsc | 159 +++++++++++++++++++++ scripts/mikrotik/hello.rsc | 1 + scripts/mikrotik/test-firewall-external.sh | 45 ++++++ scripts/mikrotik/test-firewall-internal.sh | 44 ++++++ 6 files changed, 267 insertions(+) create mode 100644 scripts/mikrotik/README.md create mode 100644 scripts/mikrotik/firewall.rsc create mode 100644 scripts/mikrotik/hello.rsc create mode 100755 scripts/mikrotik/test-firewall-external.sh create mode 100755 scripts/mikrotik/test-firewall-internal.sh diff --git a/.zshrc b/.zshrc index 59ffa83..c452ca8 100644 --- a/.zshrc +++ b/.zshrc @@ -1587,6 +1587,21 @@ zshrc_load_library() { ssh "$userAtHost" "/file add name=${key_filename} contents=\"$(cat ~/.ssh/id_rsa.pub)\"; /user ssh-keys import user=${user} public-key-file=${key_filename}; /file remove ${key_filename};" } + mtik-exec() { + local mtik_host="${1:-rb3011}" + local script_path="${2}" + local script_name="$(basename "$script_path")" + + # Create a temporary file to store our scripts. + ssh "$mtik_host" "/file/add type=directory name=scripts" > /dev/null + + # Upload the script to the MikroTik router, under the scripts folder. + scp "$script_path" "$mtik_host:/scripts/$script_name" + + # Connect to the MikroTik router and execute the script + ssh "$mtik_host" "/import scripts/$script_name" + } + rf-link() { iw dev "$(iw dev | grep Interface | awk '{ print $2 }' | head -n1)" link } diff --git a/scripts/mikrotik/README.md b/scripts/mikrotik/README.md new file mode 100644 index 0000000..2d11b92 --- /dev/null +++ b/scripts/mikrotik/README.md @@ -0,0 +1,3 @@ +# Mikrotik + +- [Packet Flow Diagrams](https://help.mikrotik.com/docs/display/ROS/Packet+Flow+in+RouterOS) diff --git a/scripts/mikrotik/firewall.rsc b/scripts/mikrotik/firewall.rsc new file mode 100644 index 0000000..05e5534 --- /dev/null +++ b/scripts/mikrotik/firewall.rsc @@ -0,0 +1,159 @@ +################## +# RESET FIREWALL # +################## +/ip firewall filter remove [find] +/ip firewall nat remove [find] +/ip firewall mangle remove [find] +/ip firewall raw remove [find] + +########## +# FILTER # +########## +/ip/firewall/filter + +# TODO: Label ether1 as WAN. + +add chain=forward in-interface=ether1 connection-state=new connection-nat-state=dstnat action=accept comment="Accept new forwarding connections from WAN" +add chain=input in-interface=ether1 connection-state=new connection-nat-state=dstnat action=accept comment="Accept new input connections from WAN" +add chain=input in-interface=ether1 connection-state=established,related,untracked action=accept comment="Accept established, related, and untracked input connections from WAN" +add chain=input connection-state=invalid action=drop comment="Drop invalid input connections" + +add chain=input protocol=icmp in-interface=ether1 action=accept comment="Allow ICMP" +add chain=input protocol=tcp in-interface=ether1 any-port=8291 action=accept comment="Allow Winbox" +add chain=input protocol=udp dst-port=123 action=accept comment="Allow NTP" +add chain=input in-interface=ether1 action=drop comment="Drop all other input traffic" + +# TODO: Move this rule near top? +add chain=forward connection-state=established,related action=fasttrack-connection hw-offload=yes comment="Fasttrack established and related connections" + +add chain=forward connection-state=established,related action=accept comment="Accept established and related forwarding connections" +add chain=forward connection-state=invalid action=drop comment="Drop invalid forwarding connections" +add chain=forward in-interface=ether1 connection-state=new connection-nat-state=!dstnat action=drop comment="Drop new forwarding connections from WAN" + +# Guidelines +# - Skip IPv6 +# - Restrict TCP/UDP ports specifically (one or the other, not both) +# - Sort them +# - Create separate chains for each host? +# +# 22/tcp; SSH +# 80/tcp; HTTP +# 443/tcp; HTTPS +# 443/udp; HTTP/3 +# 1194/udp; OpenVPN +# 25565/tcp; Minecraft Server 1 +# 25566/tcp; Minecraft Server 2 +# 27015/tcp; Valve +# 27015/udp; Valve +# 51820/udp; WireGuard +# +# Private: +# 81/tcp; SWAG Dashboard +# 5432/tcp; PostgreSQL +# 5432/udp; PostgreSQL +# +# Unknown, TCP or UDP: +# 6881/tcp; BitTorrent +# 111/tcp; NFSv3 (private) +# 2049/tcp; NFSv3 (private) +# +# Unknown: +# 18080/tcp; Service 18080 +# 18081/tcp; Service 18081 +# 8443/tcp; HTTPS Alt +# 2049/tcp; NFS +# 32765/tcp; RPC +# 32767/tcp; RPC + +# Allow SSH (IPv4) +add chain=input protocol=tcp dst-port=22 action=accept comment="Allow SSH" + +# Allow mDNS (IPv4) +add chain=input protocol=udp dst-address=224.0.0.251 dst-port=5353 action=accept comment="Allow mDNS" + +# Limit SSH (IPv4) +add chain=input protocol=tcp dst-port=22 connection-state=new action=jump jump-target=limit-ssh +add chain=limit-ssh connection-state=new action=add-src-to-address-list address-list=ssh_blacklist address-list-timeout=1d +add chain=limit-ssh connection-state=new src-address-list=ssh_blacklist action=drop + +# Allow specific ports (IPv4) +add chain=input protocol=tcp dst-port=25 action=accept comment="Allow SMTP" +add chain=input protocol=udp dst-port=53 action=accept comment="Allow DNS" +add chain=input protocol=udp dst-port=67 action=accept comment="Allow DHCP" +add chain=input protocol=tcp dst-port=80 action=accept comment="Allow HTTP" +add chain=input protocol=tcp dst-port=443 action=accept comment="Allow HTTPS" +add chain=input protocol=udp dst-port=1194 action=accept comment="Allow OpenVPN" +add chain=input protocol=tcp dst-port=6881 action=accept comment="Allow BitTorrent" +add chain=input protocol=tcp dst-port=25565 action=accept comment="Allow Minecraft Server 1" +add chain=input protocol=tcp dst-port=25566 action=accept comment="Allow Minecraft Server 2" +add chain=input protocol=tcp dst-port=27015 action=accept comment="Allow Game Server" +add chain=input protocol=udp dst-port=51820 action=accept comment="Allow WireGuard" +add chain=input protocol=tcp dst-port=18080 action=accept comment="Allow Service 18080" +add chain=input protocol=tcp dst-port=18081 action=accept comment="Allow Service 18081" +add chain=input protocol=tcp dst-port=8443 action=accept comment="Allow HTTPS Alt" +add chain=input protocol=tcp dst-port=5432 action=accept comment="Allow PostgreSQL" +add chain=input protocol=tcp dst-port=2049 action=accept comment="Allow NFS" +add chain=input protocol=tcp dst-port=111 action=accept comment="Allow Portmapper" +add chain=input protocol=tcp dst-port=32765 action=accept comment="Allow RPC" +add chain=input protocol=tcp dst-port=32767 action=accept comment="Allow RPC" +add chain=input protocol=tcp dst-port=81 action=accept comment="Allow HTTP Alt" + +# Allow specific ports (IPv6) +add chain=input protocol=tcp dst-port=22 action=accept comment="Allow SSH (v6)" +add chain=input protocol=udp dst-address=ff02::fb dst-port=5353 action=accept comment="Allow mDNS (v6)" +add chain=input protocol=tcp dst-port=25 action=accept comment="Allow SMTP (v6)" +add chain=input=protocol=udp dst-port=53 action=accept comment="Allow DNS (v6)" +add chain=input protocol=udp dst-port=67 action=accept comment="Allow DHCP (v6)" +add chain=input protocol=tcp dst-port=80 action=accept comment="Allow HTTP (v6)" +add chain=input protocol=tcp dst-port=443 action=accept comment="Allow HTTPS (v6)" +add chain=input protocol=udp dst-port=1194 action=accept comment="Allow OpenVPN (v6)" +add chain=input protocol=tcp dst-port=6881 action=accept comment="Allow BitTorrent (v6)" +add chain=input protocol=tcp dst-port=25565 action=accept comment="Allow Minecraft Server 1 (v6)" +add chain=input protocol=tcp dst-port=25566 action=accept comment="Allow Minecraft Server 2 (v6)" +add chain=input protocol=tcp dst-port=27015 action=accept comment="Allow Game Server (v6)" +add chain=input protocol=udp dst-port=51820 action=accept comment="Allow WireGuard (v6)" +add chain=input protocol=tcp dst-port=18080 action=accept comment="Allow Service 18080 (v6)" +add chain=input protocol=tcp dst-port=18081 action=accept comment="Allow Service 18081 (v6)" +add chain=input protocol=tcp dst-port=8443 action=accept comment="Allow HTTPS Alt (v6)" +add chain=input protocol=tcp dst-port=5432 action=accept comment="Allow PostgreSQL (v6)" +add chain=input protocol=tcp dst-port=2049 action=accept comment="Allow NFS (v6)" +add chain=input protocol=tcp dst-port=111 action=accept comment="Allow Portmapper (v6)" +add chain=input protocol=tcp dst-port=32765 action=accept comment="Allow RPC (v6)" +add chain=input protocol=tcp dst-port=32767 action=accept comment="Allow RPC (v6)" +add chain=input protocol=tcp dst-port=81 action=accept comment="Allow HTTP Alt (v6)" + +# Drop everything else +add chain=input action=drop comment="Drop all other traffic" + +# TODO: What traffic might I want to log? + +##################################### +# NETWORK ADDRESS TRANSLATION (NAT) # +##################################### +/ip/firewall/nat + +# TODO: These should probably be input rules way sooner. +add chain=dstnat protocol=udp dst-port=123 action=accept comment="Allow NTP" +add chain=dstnat protocol=tcp dst-port=4460 action=accept comment="Allow NTS" + +# TODO: Shouldn't this be using +add chain=srcnat src-address-list=list_wireguard out-interface=ether1 action=masquerade comment="Masquerade WireGuard traffic" + +# TODO: This seems wrong... +add chain=srcnat out-interface=ether1 action=masquerade comment="Masquerade all other traffic" + +# TODO: point this to Alan's local port 22? +# to-ports=22 +add chain=dstnat protocol=tcp dst-port=2212 in-interface=ether1 action=dst-nat to-addresses=192.168.1.12 comment="Redirect 2212 to git.alanocull.com for SSH" + +# TODO: Get rid of these port ignores... +add chain=dstnat protocol=udp dst-port=!123,13221-13230 in-interface=ether1 action=dst-nat to-addresses=192.168.1.10 comment="Redirect all other UDP traffic to default device (maxocull.com)" +add chain=dstnat protocol=tcp dst-port=!4460 in-interface=ether1 action=dst-nat to-addresses=192.168.1.10 comment="Redirect all other TCP traffic to default device (maxocull.com)" + +########## +# MANGLE # +########## + +####### +# RAW # +####### diff --git a/scripts/mikrotik/hello.rsc b/scripts/mikrotik/hello.rsc new file mode 100644 index 0000000..41fca6b --- /dev/null +++ b/scripts/mikrotik/hello.rsc @@ -0,0 +1 @@ +:put "hello, world" diff --git a/scripts/mikrotik/test-firewall-external.sh b/scripts/mikrotik/test-firewall-external.sh new file mode 100755 index 0000000..914cd9d --- /dev/null +++ b/scripts/mikrotik/test-firewall-external.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +if [ "$(id -u)" -ne 0 ]; then + exec sudo "$0" "$@" +fi + +info() { + message=$1 + + printf "%s\n" "${message}" +} + +info "Does a deep DNS entry resolve?" +dig www.maxocull.com @9.9.9.9 +tries=1 + +info "Can we ping it?" +ping -c1 www.maxocull.com + +info "Does it supply DNS?" +dig www.maxocull.com @maxocull.com + +info "These TCP services should be OPEN:" +nmap -sS -p 22,80,443 maxocull.com --dns-servers 9.9.9.9 + +info "These UDP services should be OPEN:" +nmap -sU -p 443,1194,51820 maxocull.com --dns-servers 9.9.9.9 + +info "These TCP services should be CLOSED:" +nmap -sS -p 81,5432 maxocull.com --dns-servers 9.9.9.9 +nmap -sU -p 5432 maxocull.com --dns-servers 9.9.9.9 + +info "Is it serving my webpage?" +curl -L 'https://maxocull.com' | grep '' | head -n1 + +info "Does SSH on 22/tcp reach Entourage?" +ssh entourage "hostname" + +info "Does SSH on 2212/tcp reach git.alanocull.com?" +ssh git.alanocull.com "hostname" + +info "Does the router supply NTP?" +chronyc ntpdata -s maxocull.com + +# TODO: Does the router supply NTS? +# ... diff --git a/scripts/mikrotik/test-firewall-internal.sh b/scripts/mikrotik/test-firewall-internal.sh new file mode 100755 index 0000000..e949fea --- /dev/null +++ b/scripts/mikrotik/test-firewall-internal.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +if [ "$(id -u)" -ne 0 ]; then + exec sudo "$0" "$@" +fi + +info() { + message=$1 + + printf "%s\n" "${message}" +} + +info "Does a deep DNS entry resolve?" +dig www.maxocull.com @192.168.1.1 +tries=1 + +info "Can we ping it?" +ping -c1 www.maxocull.com + +info "Does the router supply DNS?" +dig dns.quad9.net @192.168.1.1 + +info "Do local DNS entries resolve?" +dig leviathan @192.168.1.1 + +info "These Mikrotik TCP services should be OPEN:" +nmap -sS -p 22,80 192.168.1.1 + +info "These Entourage TCP services should be OPEN:" +nmap -sS -p 22,80,443 192.168.1.10 + +info "Is it serving my webpage?" +curl -L 'https://maxocull.com' | grep '<title>' | head -n1 + +info "Does SSH on 22/tcp reach Entourage?" +ssh entourage "hostname" + +info "Does SSH on 2212/tcp reach git.alanocull.com?" +ssh git.alanocull.com "hostname" + +info "Does the router supply NTP?" +chronyc ntpdata 192.168.1.1 + +# TODO: Does the router supply NTS? +# ...