aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--GeneratePSK51
-rw-r--r--check-certificates52
-rw-r--r--check-routeros-update42
-rw-r--r--collect-wireless-mac64
-rw-r--r--daily-psk41
-rw-r--r--dhcp-lease-comment22
-rw-r--r--dhcp-to-dns75
-rw-r--r--email-backup51
-rw-r--r--email-daily-psk47
-rw-r--r--ethernet-to-default17
-rw-r--r--forward-sms29
-rw-r--r--global-config42
-rw-r--r--ipv6-update38
-rw-r--r--learn-mac-based-vlan12
-rw-r--r--lease-script17
-rw-r--r--leds-day-mode6
-rw-r--r--leds-night-mode6
-rw-r--r--manage-umts26
-rw-r--r--netwatch-syslog14
-rw-r--r--ppp-on-up13
-rw-r--r--remove-packages6
-rw-r--r--rotate-ntp12
-rw-r--r--script-updates17
-rw-r--r--script2script6
-rw-r--r--ssh-keys-import10
-rw-r--r--super-mario-theme66
-rw-r--r--update-gre-address30
-rw-r--r--update-tunnelbroker30
28 files changed, 842 insertions, 0 deletions
diff --git a/GeneratePSK b/GeneratePSK
new file mode 100644
index 0000000..c40bb7c
--- /dev/null
+++ b/GeneratePSK
@@ -0,0 +1,51 @@
+# RouterOS script: GeneratePSK
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# return pseudo-random string for PSK
+
+:local date [ / system clock get date ];
+
+# 0-30 for days of month
+:local
+secret1 { "Abusive"; "Aggressive"; "Bored"; "Chemical"; "Cold"; "Cruel";
+ "Curved"; "Delightful"; "Discreet"; "Elite"; "Evasive"; "Faded"; "Flat";
+ "Future"; "Grandiose"; "Hanging"; "Humorous"; "Interesting"; "Magenta";
+ "Magnificent"; "Numerous"; "Optimal"; "Pathetic"; "Possessive";
+ "Remarkable"; "Rightful"; "Ruthless"; "Stale"; "Unusual"; "Useless";
+ "Various" };
+# 0-11 for month of year
+:local secret2 { "Adhesive"; "Amusing"; "Astonishing"; "Frantic";
+ "Kindhearted"; "Limping"; "Roasted"; "Robust"; "Staking"; "Thundering";
+ "Ultra"; "Unusual" };
+# 0-6 for days of week
+:local secret3 { "Belief"; "Button"; "Curtain"; "Edge"; "Jewel"; "String";
+ "Whistle" };
+
+:local months { "jan"; "feb"; "mar"; "apr"; "may"; "jun"; "jul"; "aug"; "sep";
+ "oct"; "nov"; "dec" };
+:local monthtbl { 0; 3; 3; 6; 1; 4; 6; 2; 5; 0; 3; 5 };
+
+:local monthstr [ :pick $date 0 3 ];
+:local month;
+:local day [ :pick $date 4 6 ];
+:local century [ :pick $date 7 9 ];
+:local year [ :pick $date 9 11 ];
+
+# get numeric value for month
+:for mindex from=0 to=[ :len $months ] do={
+ :if ([ :pick $months $mindex ] = $monthstr) do={
+ :set month $mindex;
+ };
+};
+
+# calculate day of week
+:local sum 0;
+:set sum ($sum + (2 * (3 - ($century - (($century / 4) * 4)))));
+:set sum ($sum + ($year / 4));
+:set sum ($sum + $year + $day);
+:set sum ($sum + $month);
+:set sum ($sum - (($sum / 7) * 7));
+
+:local return ([ :pick $secret1 ($day - 1) ] . [ :pick $secret2 $month ] . [ :pick $secret3 $sum ]);
+
+:return $return;
diff --git a/check-certificates b/check-certificates
new file mode 100644
index 0000000..925187d
--- /dev/null
+++ b/check-certificates
@@ -0,0 +1,52 @@
+# RouterOS script: check-certificates
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# check for certificate validity
+
+:global "identity";
+:global "email-general-to";
+:global "email-general-cc";
+
+:local months ("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec");
+
+:local currentdate [ / system clock get date ];
+
+:local currentmonthstr [ :pick $currentdate 0 3 ];
+:local currentday [ :pick $currentdate 4 6 ];
+:local currentyear [ :pick $currentdate 7 11 ];
+:local currentmonth ([ :find $months $currentmonthstr -1 ] + 1);
+:local currentstamp ($currentyear * 365 + $currentmonth * 30 + $currentday);
+
+:foreach cert in=[ / certificate find where !revoked ] do={
+ :local certname [ / certificate get $cert name ];
+ :local invaliddate [ / certificate get $cert invalid-after ];
+
+ :if ([ :len $invaliddate ] > 0) do={
+ :local invalidmonthstr [ :pick $invaliddate 0 3 ];
+ :local invalidday [ :pick $invaliddate 4 6 ];
+ :local invalidyear [ :pick $invaliddate 7 11 ];
+ :local invalidmonth ([ :find $months $invalidmonthstr -1 ] + 1);
+ :local invalidstamp ($invalidyear * 365 + invalidmonth * 30 + invalidday);
+
+ :local remaining ($invalidstamp - $currentstamp);
+
+ :if ($remaining < 15) do={
+ :local commonname [ / certificate get $cert common-name ];
+ :local fingerprint [ / certificate get $cert fingerprint ];
+ :local invalidbefore [ / certificate get $cert invalid-before ];
+ :local invalidafter [ / certificate get $cert invalid-after ];
+ / tool e-mail send to=$"email-general-to" cc=$"email-general-cc" \
+ subject=("[" . $identity . "] Certificate warning!") \
+ body=("A certificate on " . $identity . " is about to expire.\n\n" . \
+ "Certificate Name: " . $certname . "\n" . \
+ "Common Name: " . $commonname . "\n" . \
+ "Fingerprint: " . $fingerprint . "\n" . \
+ "Validity: " . $invalidbefore . " to " . $invalidafter);
+ :log warning ("A certificate is about to expire within " . $remaining . " days: " . $certname);
+ } else={
+ :log debug ("The certificate " . $certname . " expires in " . $remaining . " days.");
+ }
+ } else={
+ :log debug ("The certificate " . $certname . " is just a template.");
+ }
+}
diff --git a/check-routeros-update b/check-routeros-update
new file mode 100644
index 0000000..8cd93fe
--- /dev/null
+++ b/check-routeros-update
@@ -0,0 +1,42 @@
+# RouterOS script: check-routeros-update
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# check for RouterOS update, send notification e-mails
+
+:global "identity";
+:global "email-general-to";
+:global "email-general-cc";
+:global "sent-routeros-update-notification";
+
+:if ([ :len [ / system package find where name="wireless" ] ] > 0) do={
+ :if ([ / interface wireless cap get enabled ] = true) do={
+ :error "System is managed by CAPsMAN, not checking.";
+ }
+}
+
+:if ($"sent-routeros-update-notification" = true) do={
+ :error "Already sent the RouterOS update notification.";
+}
+
+# get some information
+:local model [ / system routerboard get model ];
+:local serialnumber [ / system routerboard get serial-number ];
+
+# check for RouterOS
+/ system package update check-for-updates without-paging;
+:local installedversion [ / system package update get installed-version ];
+:local latestversion [ / system package update get latest-version ];
+:local channel [ / system package update get channel ];
+
+:if ($installedversion != $latestversion) do={
+ / tool e-mail send to=$"email-general-to" cc=$"email-general-cc" \
+ subject=("[" . $identity . "] RouterOS update notification") \
+ body=("There is a RouterOS update available\n\n" . \
+ "Routerboard: " . $model . "\n" . \
+ "Serial number: " . $serialnumber . "\n" . \
+ "Hostname: " . $identity . "\n" . \
+ "Channel: " . $channel . "\n" . \
+ "Installed: " . $installedversion . "\n" . \
+ "Available: " . $latestversion);
+ :set "sent-routeros-update-notification" true;
+}
diff --git a/collect-wireless-mac b/collect-wireless-mac
new file mode 100644
index 0000000..ee93a11
--- /dev/null
+++ b/collect-wireless-mac
@@ -0,0 +1,64 @@
+# RouterOS script: collect-wireless-mac
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# collect wireless mac adresses in access list
+#
+# this supports local wireless and caps-man when updating paths:
+# $ sed -i '/^$/,$s/caps-man/interface wireless/' collect-wireless-mac
+# $ sed -i '/^$/,$s/interface wireless/caps-man/' collect-wireless-mac
+
+:global "identity";
+:global "email-general-to";
+:global "email-general-cc";
+
+:local "place-before" [ / caps-man access-list find where comment="--- collected above ---" disabled ];
+:if ([ :len $"place-before" ] = 0) do={
+ :error "Missing disabled access-list entry with comment '--- collected above ---'";
+}
+
+:foreach regtbl in=[ / caps-man registration-table find ] do={
+ :local mac [ / caps-man registration-table get $regtbl mac-address ];
+ :local acclst [ :pick [ / caps-man access-list find where mac-address=$mac ] 0 ];
+ :if ( [ :len $acclst ] = 0 ) do={
+ :local hostname "no dhcp lease";
+ :local address "no dhcp lease";
+ :local lease [ / ip dhcp-server lease find where mac-address=$mac ];
+ :if ( [ :len $lease ] > 0 ) do={
+ :set hostname [ / ip dhcp-server lease get $lease host-name ];
+ :set address [ / ip dhcp-server lease get $lease address ];
+ }
+ :if ( [ :len $hostname ] = 0 ) do={
+ :set hostname "no hostname";
+ }
+ :if ( [ :len $address ] = 0 ) do={
+ :set address "no address";
+ }
+ :local regentry [ / caps-man registration-table find where mac-address=$mac ];
+ :local interface [ / caps-man registration-table get $regentry interface ];
+ :local ssid;
+ :if ("caps-man" = ("caps" . "-man")) do={
+ :set ssid [ / caps-man registration-table get $regentry ssid ];
+ } else={
+ # keep two spaces here to protect against replace!
+ :set ssid [ / interface wireless get [ find where name=$interface ] ssid ];
+ }
+ :local datetime ([ / system clock get date ] . " " . [ / system clock get time ]);
+ :local message ("unknown MAC address " . $mac . " (" . $hostname . ") first seen on " . \
+ $datetime . " connected to SSID " . $ssid . ", interface " . $interface);
+ / log info $message;
+ / caps-man access-list add place-before=$"place-before" comment=$message mac-address=$mac disabled=yes;
+ / tool e-mail send to=$"email-general-to" cc=$"email-general-cc" \
+ subject=("[" . $identity . "] " . $mac . " connected to " . $ssid) \
+ body=("A device with unknown MAC address connected to " . $ssid . " on " . $identity . ".\n\n" . \
+ "Controller: " . $identity . "\n" . \
+ "Interface: " . $interface . "\n" . \
+ "SSID: " . $ssid . "\n" . \
+ "MAC: " . $mac . "\n" . \
+ "Hostname: " . $hostname . "\n" . \
+ "Address: " . $address . "\n" . \
+ "Date: " . $datetime);
+ } else={
+ :local comment [ / caps-man access-list get $acclst comment ];
+ :log debug ("MAC address " . $mac . " already known: " . $comment);
+ }
+}
diff --git a/daily-psk b/daily-psk
new file mode 100644
index 0000000..abb1f91
--- /dev/null
+++ b/daily-psk
@@ -0,0 +1,41 @@
+# RouterOS script: daily-psk
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# update daily PSK (pre shared key)
+
+:global "daily-psk-match-comment";
+
+# check mail server
+:if ([ / tool netwatch get [ find where comment=[ / tool e-mail get address ] ] status ] != "up" ) do={
+ :error "Mail server is not up.";
+}
+
+# check time
+:if ([ / system ntp client get status ] != "synchronized") do={
+ :error "Time is not yet synchronized from ntp.";
+}
+
+:local GeneratePSK [ :parse [ / system script get GeneratePSK source ] ];
+
+:local newpsk [ $GeneratePSK ];
+
+:local sendmail 0;
+
+:foreach acclist in=[ / interface wireless access-list find where comment~$"daily-psk-match-comment" ] do={
+ :local interface [ / interface wireless access-list get $acclist interface ];
+ :local ssid [ / interface wireless get $interface ssid ];
+ :local oldpsk [ / interface wireless access-list get $acclist private-pre-shared-key ];
+
+ :if ($newpsk != $oldpsk) do={
+ :log info ("Updating daily PSK for " . $interface . " to " . $newpsk . " (was " . $oldpsk . ")");
+ / interface wireless access-list set $acclist private-pre-shared-key=$newpsk;
+
+ :set sendmail 1;
+ }
+}
+
+:if ($sendmail = 1) do={
+ / system script run email-daily-psk;
+}
+
+/ system scheduler set disabled=yes [ find where name=daily-psk disabled=no ];
diff --git a/dhcp-lease-comment b/dhcp-lease-comment
new file mode 100644
index 0000000..f3a081c
--- /dev/null
+++ b/dhcp-lease-comment
@@ -0,0 +1,22 @@
+# RouterOS script: dhcp-lease-comment
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# update dhcp-server lease comment with infos from access-list
+#
+# this supports local wireless and caps-man when updating paths:
+# $ sed -i '/^$/,$s/caps-man/interface wireless/' dhcp-lease-comment
+# $ sed -i '/^$/,$s/interface wireless/caps-man/' dhcp-lease-comment
+
+:foreach lease in=[ / ip dhcp-server lease find where dynamic=yes ] do={
+ :local macaddress [ / ip dhcp-server lease get $lease mac-address ];
+ :local oldcomment [ / ip dhcp-server lease get $lease comment ];
+ :local newcomment;
+ :local accesslst [ :pick [ / caps-man access-list find where mac-address=$macaddress ] 0 ];
+ :if ( [ :len $accesslst ] > 0 ) do={
+ :set newcomment [ / caps-man access-list get $accesslst comment ];
+ }
+ :if ([ :len $newcomment ] != 0 && $oldcomment != $newcomment) do={
+ :log info ("Updating comment for DHCP lease " . $macaddress . ": " . $newcomment);
+ / ip dhcp-server lease set comment=$newcomment $lease;
+ }
+}
diff --git a/dhcp-to-dns b/dhcp-to-dns
new file mode 100644
index 0000000..40276ef
--- /dev/null
+++ b/dhcp-to-dns
@@ -0,0 +1,75 @@
+# RouterOS script: dhcp-to-dns
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# check DHCP leases and add/remove/update DNS entries
+
+:global "identity";
+:global "domain";
+:global "hostname-in-zone";
+
+:local zone;
+:if ($"hostname-in-zone" = true) do={
+ :set zone ("dhcp." . $identity . "." . $domain);
+} else={
+ :set zone ("dhcp." . $domain);
+}
+:local ttl "00:05:00";
+:local hostname;
+:local fqdn;
+:local dnsip;
+:local dhcpip;
+:local dnsnode;
+:local dhcpnode;
+
+:foreach static in=[ / ip dns static find where name ~ (".*\\." . $zone) ] do={
+ :set fqdn [ / ip dns static get $static name ];
+ :set hostname [ :pick $fqdn 0 ( [ :len $fqdn ] - ( [ :len $zone ] + 1 ) ) ];
+ :set dhcpnode [ / ip dhcp-server lease find where host-name=$hostname dynamic=yes ];
+ :if ( [ :len $dhcpnode ] > 0) do={
+ :log debug ("Lease for " . $hostname . " still exists. Not deleting.");
+ } else={
+ :local found false;
+ :log info ("Lease expired for " . $hostname . ", deleting DNS entry.");
+ / ip dns static remove $static;
+ }
+}
+
+:foreach lease in=[ / ip dhcp-server lease find where dynamic=yes ] do={
+ :local mac [ / ip dhcp-server lease get $lease mac-address ];
+ :set dhcpip [ / ip dhcp-server lease get $lease address ];
+ :local comment ("managed by dhcp-to-dns for " . $mac);
+ :set hostname [ / ip dhcp-server lease get $lease host-name ];
+
+ :while ($hostname ~ " ") do={
+ :local pos [ :find $hostname " " ];
+ :set hostname ( [ :pick $hostname 0 $pos ] . [ :pick $hostname ($pos + 1) 999 ] );
+ };
+
+ :if ( [ :len $hostname ] > 0) do={
+ :set fqdn ( $hostname . "." . $zone );
+ :set dnsnode [ / ip dns static find where name=$fqdn ];
+ :if ( [ :len $dnsnode ] > 0 ) do={
+ :set dnsip [ / ip dns static get $dnsnode address ];
+
+ :local leases [ / ip dhcp-server lease find where host-name=$hostname dynamic=yes ];
+ :local hostnamecount [ :len [ / ip dhcp-server lease find where host-name=$hostname dynamic=yes ] ];
+ :if ( $hostnamecount > 1) do={
+ :foreach j,lease in=$leases do={
+ :if ($j + 1 = $hostnamecount) do={
+ :set dhcpip [ / ip dhcp-server lease get $lease address ];
+ }
+ }
+ }
+
+ :if ( $dnsip = $dhcpip ) do={
+ :log debug ("DNS entry for " . $fqdn . " does not need updating.");
+ } else={
+ :log info ("Replacing DNS entry for " . $fqdn . ", new address is " . $dhcpip . ".");
+ / ip dns static set name=$fqdn address=$dhcpip ttl=$ttl comment=$comment $dnsnode;
+ }
+ } else={
+ :log info ("Adding new DNS entry for " . $fqdn . ", address is " . $dhcpip . ".");
+ / ip dns static add name=$fqdn address=$dhcpip ttl=$ttl comment=$comment;
+ }
+ }
+}
diff --git a/email-backup b/email-backup
new file mode 100644
index 0000000..1c05ff1
--- /dev/null
+++ b/email-backup
@@ -0,0 +1,51 @@
+# RouterOS script: email-backup
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# create and email backup and config file
+
+:global "identity";
+:global "domain";
+:global "email-backup-to";
+:global "email-backup-cc";
+:global "backup-send-binary";
+:global "backup-send-export";
+:global "backup-password";
+
+# filename based on identity
+:local filename ($identity . "." . $domain);
+
+# get some system information
+:local model [ / system routerboard get model ];
+:local serialnumber [ / system routerboard get serial-number ];
+:local channel [ / system package update get channel ];
+:local installedversion [ / system package update get installed-version ];
+
+# create and email binary backup
+:if ($"backup-send-binary" = true) do={
+ / system backup save name=$filename password=$"backup-password";
+ / delay delay-time=10;
+ / tool e-mail send to=$"email-backup-to" cc=$"email-backup-cc" \
+ subject=("[" . $identity . "] Backup") \
+ body=("Backup file for " . $identity . " is attached.\n\n" . \
+ "Routerboard: " . $model . "\n" . \
+ "Serial number: " . $serialnumber . "\n" . \
+ "Hostname: " . $identity . "\n" . \
+ "Channel: " . $channel . "\n" . \
+ "RouterOS: " . $installedversion) \
+ file=($filename . ".backup");
+}
+
+# create and email configuration export
+:if ($"backup-send-export"= true) do={
+ / export file=$filename;
+ / delay delay-time=10;
+ / tool e-mail send to=$"email-backup-to" cc=$"email-backup-cc" \
+ subject=("[" . $identity . "] Config") \
+ body=("Config file for " . $identity . " is attached.\n\n" . \
+ "Routerboard: " . $model . "\n" . \
+ "Serial number: " . $serialnumber . "\n" . \
+ "Hostname: " . $identity . "\n" . \
+ "Channel: " . $channel . "\n" . \
+ "RouterOS: " . $installedversion) \
+ file=($filename . ".rsc");
+}
diff --git a/email-daily-psk b/email-daily-psk
new file mode 100644
index 0000000..af991ca
--- /dev/null
+++ b/email-daily-psk
@@ -0,0 +1,47 @@
+# RouterOS script: email-daily-psk
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# email daily PSK (pre shared key)
+
+:global "identity";
+:global "email-general-to";
+:global "email-general-cc";
+:global "daily-psk-match-comment";
+
+:local "seen-ssids" { "" };
+
+:foreach acclist in=[ / interface wireless access-list find where comment~$"daily-psk-match-comment" ] do={
+ :local interface [ / interface wireless access-list get $acclist interface ];
+ :local ssid [ / interface wireless get $interface ssid ];
+ :local psk [ / interface wireless access-list get $acclist private-pre-shared-key ];
+
+ :local seen 0;
+ :foreach "seen-ssid" in=$"seen-ssids" do={
+ :if ($"seen-ssid" = $ssid) do={
+ :set seen 1;
+ }
+ }
+
+ :if ($seen = 0) do={
+ :set $"seen-ssids" { $"seen-ssids"; $ssid };
+
+ :local host "www.eworm.de"
+ :local srcpath ("/cgi-bin/cqrlogo-wifi.cgi" . \
+ "?scale=8" . \
+ "&level=1" . \
+ "&ssid=" . $ssid . \
+ "&pass=" . $psk);
+
+ / tool fetch mode=https check-certificate=yes-without-crl address=$host host=$host \
+ src-path=$srcpath dst-path=qrcode-daily.png;
+
+ / tool e-mail send to=$"email-general-to" cc=$"email-general-cc" \
+ subject=("[" . $identity . "] daily PSK " . $ssid) \
+ body=("This is the daily PSK on " . $identity . ":\n\n" . \
+ "SSID: " . $ssid . "\n" . \
+ "PSK: " . $psk . "\n" . \
+ "Date: " . [ / system clock get date ] . "\n\n" . \
+ "https://" . $host . $srcpath) \
+ file=qrcode-daily.png;
+ }
+}
diff --git a/ethernet-to-default b/ethernet-to-default
new file mode 100644
index 0000000..ed86cc7
--- /dev/null
+++ b/ethernet-to-default
@@ -0,0 +1,17 @@
+# RouterOS script: ethernet-to-default
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# reset ethernet interfaces to default bridge
+
+:foreach interface in=[ / interface bridge port find where comment~"^default:" ] do={
+ :local comment [ / interface bridge port get $interface comment ];
+ :local "interface-name" [ / interface bridge port get $interface interface ];
+ :local "bridge-default" [ :pick $comment 8 [ :len $comment ] ];
+ :local "bridge-current" [ / interface bridge port get $interface bridge ];
+ :if ($"bridge-default" != $"bridge-current") do={
+ :log info ("Reverting interface " . $"interface-name" . " to default bridge " . $"bridge-default");
+ / interface bridge port set bridge=$"bridge-default" $interface;
+ } else={
+ :log debug ("Interface " . $"interface-name" . " already connected to default bridge " $"bridge-default");
+ }
+}
diff --git a/forward-sms b/forward-sms
new file mode 100644
index 0000000..f2d03fe
--- /dev/null
+++ b/forward-sms
@@ -0,0 +1,29 @@
+# RouterOS script: forward-sms
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# forward SMS to e-mail
+
+:global "identity";
+:global "email-general-to";
+:global "email-general-cc";
+
+# check mail server
+:if ([ / tool netwatch get [ find where comment=[ / tool e-mail get address ] ] status ] != "up" ) do={
+ :error "Mail server is not up.";
+}
+
+# forward SMS in a loop
+:foreach sms in=[ / tool sms inbox find ] do={
+ :local message [ / tool sms inbox get $sms message ];
+ :local phone [ / tool sms inbox get $sms phone ];
+ :local timestamp [ / tool sms inbox get $sms timestamp ];
+ :local type [ / tool sms inbox get $sms type ];
+ / tool e-mail send to=$"email-general-to" cc=$"email-general-cc" \
+ subject=("[" . $identity . "] SMS Forwarding") \
+ body=("A message was received by " . $identity . ":\n\n" . \
+ "Phone: " . $phone . "\n" . \
+ "Timestamp: " . $timestamp . "\n" . \
+ "Type: " . $type . "\n\n" . \
+ "Message:\n" . $message);
+ / tool sms inbox remove $sms;
+}
diff --git a/global-config b/global-config
new file mode 100644
index 0000000..534df40
--- /dev/null
+++ b/global-config
@@ -0,0 +1,42 @@
+# RouterOS script: global-config
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# global configuration
+
+# This is used for DNS and backup file.
+:global "domain" "example.com";
+:global "hostname-in-zone" true;
+
+# These addresses are used to send e-mails to. The to-addresses need
+# to be filled, cc-addresses can be empty, one address or a comma
+# separated list of addresses.
+:global "email-general-to" "mail@example.com";
+:global "email-general-cc" "another@example.com";
+:global "email-backup-to" "mail@example.com";
+:global "email-backup-cc" "";
+
+# This defines what backups to generate and what password to use.
+:global "backup-send-binary" false;
+:global "backup-send-export" true;
+:global "backup-password" "v3ry-s3cr3t";
+
+# This is used to update AAAA records and firewall address-list.
+:global "ipv6-interface" "br-local";
+:global "ipv6-pool" "telekom";
+
+# These settings are used to update gre interface settings based on
+# remote peer configuration.
+:global "gre-cert-prefix" "ikev2-";
+:global "gre-int-prefix" "gre-";
+
+# Access-list entries matching this comment are updated with daily
+# pseudo-random PSK.
+:global "daily-psk-match-comment" "Daily PSK";
+
+# This address should resolve ntp servers and is used to update
+# ntp settings. A pool can rotate servers.
+:global "ntp-pool" "pool.ntp.org";
+
+# Do *NOT* change these!
+:global "sent-routeros-update-notification" false;
+:global "identity" [ / system identity get name ];
diff --git a/ipv6-update b/ipv6-update
new file mode 100644
index 0000000..b434e05
--- /dev/null
+++ b/ipv6-update
@@ -0,0 +1,38 @@
+# RouterOS script: ipv6-update
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# update firewall and dns settings on IPv6 prefix change
+
+:global "ipv6-interface";
+:global "ipv6-pool";
+
+:local addrlist [ / ipv6 firewall address-list find where comment=("ipv6-pool-" . $"ipv6-pool") ];
+:local oldprefix [ / ipv6 firewall address-list get $addrlist address ];
+
+# give the interfaces a moment to receive their addresses
+:delay 2s;
+
+if ($oldprefix != $"pd-prefix") do={
+ :log info ("Updating ipv6 address list with new IPv6 prefix " . $"pd-prefix");
+ / ipv6 firewall address-list set address=$"pd-prefix" $addrlist;
+
+ :local oldprefix56 [ :pick $oldprefix 0 [ :find $oldprefix "00::/56" ] ];
+ :local oldprefix64 [ :pick $oldprefix 0 [ :find $oldprefix "::/56" ] ];
+
+ :local newprefix [ / ipv6 address get [ / ipv6 address find where from-pool=$"ipv6-pool" interface=$"ipv6-interface" ] address ];
+ :local newprefix64 [ :pick $newprefix 0 [ :find $newprefix "::/64" ] ];
+
+ :foreach record in=[ / ip dns static find where address~$oldprefix56 ] do={
+ :local address [ / ip dns static get $record address ];
+ :local name [ / ip dns static get $record name ];
+
+ :if ( [ :len $name ] = 0) do={
+ :set name [ / ip dns static get $record regex ];
+ }
+
+ :local suffix [ :pick $address [ :len $oldprefix64 ] [ :len $address ] ];
+
+ :log info ("Updating dns record for " . $name . ": " . $address . " -> " . $newprefix64 . $suffix);
+ / ip dns static set address=($newprefix64 . $suffix) $record;
+ }
+}
diff --git a/learn-mac-based-vlan b/learn-mac-based-vlan
new file mode 100644
index 0000000..34f7e09
--- /dev/null
+++ b/learn-mac-based-vlan
@@ -0,0 +1,12 @@
+# RouterOS script: learn-mac-based-vlan
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# learn MAC address for MAC-based-VLAN
+
+:local NewVlanId 33;
+
+/ log info ("MAC-based-VLAN: learning MAC address " . $leaseActMAC . " for VLAN " . $NewVlanId . ".");
+
+:if ( [ :len [ / interface ethernet switch mac-based-vlan find where src-mac-address=$leaseActMAC ] ] = 0 ) do={
+ / interface ethernet switch mac-based-vlan add src-mac-address=$leaseActMAC new-customer-vid=$NewVlanId;
+};
diff --git a/lease-script b/lease-script
new file mode 100644
index 0000000..b80b89b
--- /dev/null
+++ b/lease-script
@@ -0,0 +1,17 @@
+# RouterOS script: lease-script
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# run scripts on DHCP lease
+# ( / ip dhcp-server set lease-script=lease-script [ find ] )
+
+:local scripts { "dhcp-to-dns"; "collect-wireless-mac"; "dhcp-lease-comment" };
+
+# delay a second to give time to update the lease table
+:delay 1s;
+
+:foreach script in=$scripts do={
+ :if ([ :len [ / system script find where name=$script ] ] > 0) do={
+ :log debug ("Running script from lease-script: " . $script);
+ / system script run $script;
+ }
+}
diff --git a/leds-day-mode b/leds-day-mode
new file mode 100644
index 0000000..4eba7b1
--- /dev/null
+++ b/leds-day-mode
@@ -0,0 +1,6 @@
+# RouterOS script: leds-day-mode
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# enable LEDs
+
+/ system leds settings set all-leds-off=never;
diff --git a/leds-night-mode b/leds-night-mode
new file mode 100644
index 0000000..5941419
--- /dev/null
+++ b/leds-night-mode
@@ -0,0 +1,6 @@
+# RouterOS script: leds-night-mode
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# disable LEDs
+
+/ system leds settings set all-leds-off=immediate;
diff --git a/manage-umts b/manage-umts
new file mode 100644
index 0000000..d9e5a0b
--- /dev/null
+++ b/manage-umts
@@ -0,0 +1,26 @@
+# RouterOS script: manage-umts
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# manage UMTS interface based on ethernet and wireless status
+
+:local etherint "en1";
+:local wlanint "wl-station";
+:local umtsint "t-mobile";
+
+:local etherstatus [ / interface ethernet get $etherint running ];
+:local wlanstatus [ / interface wireless get $wlanint running ];
+
+:if ( $etherstatus = true || wlanstatus = true ) do={
+ :if ( [ / interface get $umtsint disabled ] = false ) do={
+ :log info ("Ethernet (" . $etherint . " / " . $etherstatus . ") or " . \
+ "wireless (" . $wlanint . " / " . $wlanstatus . ") is running, " . \
+ "UMTS interface " . $umtsint . " is enabled. Disabling...");
+ / interface set disabled=yes $umtsint;
+ };
+} else={
+ :if ( [ / interface get $umtsint disabled ] = true ) do={
+ :log info ("Neither ethernet (" . $etherint . ") nor wireless (" . $wlanint . ") interface is running, " . \
+ "UMTS interface " . $umtsint . " is disabled. Enabling...");
+ / interface set disabled=no $umtsint;
+ };
+};
diff --git a/netwatch-syslog b/netwatch-syslog
new file mode 100644
index 0000000..56e59ea
--- /dev/null
+++ b/netwatch-syslog
@@ -0,0 +1,14 @@
+# RouterOS script: netwatch-syslog
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# manage remote logging facilities
+
+:local remote [ /system logging action get [ :pick [ find where target=remote ] 0 ] remote ];
+
+if ([ / tool netwatch get [ find where host=$remote ] status ] = "up") do={
+ / system logging set disabled=no [ find where action=remote disabled=yes ];
+} else={
+ / system logging set disabled=yes [ find where action=remote disabled=no ];
+}
+
+/ system scheduler set disabled=yes [ find where name=netwatch-syslog disabled=no ];
diff --git a/ppp-on-up b/ppp-on-up
new file mode 100644
index 0000000..7940f2a
--- /dev/null
+++ b/ppp-on-up
@@ -0,0 +1,13 @@
+# RouterOS script: ppp-on-up
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# run scripts on ppp up
+
+# variable $interface is available in ppp on-up script
+:local dhcpclient [ / ipv6 dhcp-client find where interface=$interface ];
+
+:if ( [ :len $dhcpclient ] > 0) do={
+ / ipv6 dhcp-client disable $dhcpclient;
+ :delay 1s;
+ / ipv6 dhcp-client enable $dhcpclient;
+}
diff --git a/remove-packages b/remove-packages
new file mode 100644
index 0000000..a3bb2a0
--- /dev/null
+++ b/remove-packages
@@ -0,0 +1,6 @@
+# RouterOS script: remove-packages
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# remove packages (*.npk) from storage
+
+/ file remove [ / file find type="package" ];
diff --git a/rotate-ntp b/rotate-ntp
new file mode 100644
index 0000000..07672fb
--- /dev/null
+++ b/rotate-ntp
@@ -0,0 +1,12 @@
+# RouterOS script: rotate-ntp
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# rotate the ntp servers
+
+:global "ntp-pool";
+
+:local ntp1 [ :resolve ("0." . $"ntp-pool") ];
+:local ntp2 [ :resolve ("1." . $"ntp-pool") ];
+
+:log info ("Updating NTP servers to " . $ntp1 . " and " . $ntp2);
+/ system ntp client set primary-ntp=$ntp1 secondary-ntp=$ntp2;
diff --git a/script-updates b/script-updates
new file mode 100644
index 0000000..13480d1
--- /dev/null
+++ b/script-updates
@@ -0,0 +1,17 @@
+# RouterOS script: script-updates
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# update installed scripts from file
+
+:foreach script in=[ / system script find ] do={
+ :local scriptname [ / system script get $script name ];
+ :local scriptfile [ / file find where name=("script-updates/" . $scriptname) ];
+ :if ([ :len $scriptfile ] > 0) do={
+ :log info ("Updating script: " . $scriptname);
+ :local scriptcontent [ / file get $scriptfile content ];
+ / system script set owner=$scriptname source=$scriptcontent $script;
+ / file remove $scriptfile;
+ } else={
+ :log debug ("No update for script " . $scriptname);
+ }
+}
diff --git a/script2script b/script2script
new file mode 100644
index 0000000..dc4c5d8
--- /dev/null
+++ b/script2script
@@ -0,0 +1,6 @@
+# RouterOS script: script2script
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# change owner to "script"
+
+/ system script set owner=script [ find where owner!="script" ];
diff --git a/ssh-keys-import b/ssh-keys-import
new file mode 100644
index 0000000..56ba6a4
--- /dev/null
+++ b/ssh-keys-import
@@ -0,0 +1,10 @@
+# RouterOS script: ssh-keys-import
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# import ssh keys from file
+
+# Split files with several keys from a shell...
+# while read type key name; do echo $type $key $name > $name.pub; done < keys.pub
+# ... then transfer with scp/sftp.
+
+:foreach key in=[ / file find where type="ssh key" ] do={ / user ssh-key import user=admin public-key-file=[ / file get $key name ]; }
diff --git a/super-mario-theme b/super-mario-theme
new file mode 100644
index 0000000..d1eda3f
--- /dev/null
+++ b/super-mario-theme
@@ -0,0 +1,66 @@
+# RouterOS script: super-mario-theme
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# play Super Mario theme
+
+:local beeps {
+ { 660; 100 }; 150; { 660; 100 }; 300; { 660; 100 }; 300;
+ { 510; 100 }; 100; { 660; 100 }; 300; { 770; 100 }; 550;
+ { 380; 100 }; 575; { 510; 100 }; 450; { 380; 100 }; 400;
+ { 320; 100 }; 500; { 440; 100 }; 300; { 480; 80 }; 330;
+ { 450; 100 }; 150; { 430; 100 }; 300; { 380; 100 }; 200;
+ { 660; 80 }; 200; { 760; 50 }; 150; { 860; 100 }; 300;
+ { 700; 80 }; 150; { 760; 50 }; 350; { 660; 80 }; 300;
+ { 520; 80 }; 150; { 580; 80 }; 150; { 480; 80 }; 500;
+ { 510; 100 }; 450; { 380; 100 }; 400; { 320; 100 }; 500;
+ { 440; 100 }; 300; { 480; 80 }; 330; { 450; 100 }; 150;
+ { 430; 100 }; 300; { 380; 100 }; 200; { 660; 80 }; 200;
+ { 760; 50 }; 150; { 860; 100 }; 300; { 700; 80 }; 150;
+ { 760; 50 }; 350; { 660; 80 }; 300; { 520; 80 }; 150;
+ { 580; 80 }; 150; { 480; 80 }; 500; { 500; 100 }; 300;
+ { 760; 100 }; 100; { 720; 100 }; 150; { 680; 100 }; 150;
+ { 620; 150 }; 300; { 650; 150 }; 300; { 380; 100 }; 150;
+ { 430; 100 }; 150; { 500; 100 }; 300; { 430; 100 }; 150;
+ { 500; 100 }; 100; { 570; 100 }; 220; { 500; 100 }; 300;
+ { 760; 100 }; 100; { 720; 100 }; 150; { 680; 100 }; 150;
+ { 620; 150 }; 300; { 650; 200 }; 300; { 1020; 80 }; 300;
+ { 1020; 80 }; 150; { 1020; 80 }; 300; { 380; 100 }; 300;
+ { 500; 100 }; 300; { 760; 100 }; 100; { 720; 100 }; 150;
+ { 680; 100 }; 150; { 620; 150 }; 300; { 650; 150 }; 300;
+ { 380; 100 }; 150; { 430; 100 }; 150; { 500; 100 }; 300;
+ { 430; 100 }; 150; { 500; 100 }; 100; { 570; 100 }; 420;
+ { 585; 100 }; 450; { 550; 100 }; 420; { 500; 100 }; 360;
+ { 380; 100 }; 300; { 500; 100 }; 300; { 500; 100 }; 150;
+ { 500; 100 }; 300; { 500; 100 }; 300; { 760; 100 }; 100;
+ { 720; 100 }; 150; { 680; 100 }; 150; { 620; 150 }; 300;
+ { 650; 150 }; 300; { 380; 100 }; 150; { 430; 100 }; 150;
+ { 500; 100 }; 300; { 430; 100 }; 150; { 500; 100 }; 100;
+ { 570; 100 }; 220; { 500; 100 }; 300; { 760; 100 }; 100;
+ { 720; 100 }; 150; { 680; 100 }; 150; { 620; 150 }; 300;
+ { 650; 200 }; 300; { 1020; 80 }; 300; { 1020; 80 }; 150;
+ { 1020; 80 }; 300; { 380; 100 }; 300; { 500; 100 }; 300;
+ { 760; 100 }; 100; { 720; 100 }; 150; { 680; 100 }; 150;
+ { 620; 150 }; 300; { 650; 150 }; 300; { 380; 100 }; 150;
+ { 430; 100 }; 150; { 500; 100 }; 300; { 430; 100 }; 150;
+ { 500; 100 }; 100; { 570; 100 }; 420; { 585; 100 }; 450;
+ { 550; 100 }; 420; { 500; 100 }; 360; { 380; 100 }; 300;
+ { 500; 100 }; 300; { 500; 100 }; 150; { 500; 100 }; 300;
+ { 500; 60 }; 150; { 500; 80 }; 300; { 500; 60 }; 350;
+ { 500; 80 }; 150; { 580; 80 }; 350; { 660; 80 }; 150;
+ { 500; 80 }; 300; { 430; 80 }; 150; { 380; 80 }; 600;
+ { 500; 60 }; 150; { 500; 80 }; 300; { 500; 60 }; 350;
+ { 500; 80 }; 150; { 580; 80 }; 150; { 660; 80 }; 550;
+ { 870; 80 }; 325; { 760; 80 }; 600; { 500; 60 }; 150;
+ { 500; 80 }; 300; { 500; 60 }; 350; { 500; 80 }; 150;
+ { 580; 80 }; 350; { 660; 80 }; 150; { 500; 80 }; 300;
+ { 430; 80 }; 150; { 380; 80 }; 600; { 660; 100 }; 150;
+ { 660; 100 }; 300; { 660; 100 }; 300; { 510; 100 }; 100;
+ { 660; 100 }; 300; { 770; 100 }; 550; { 380; 100 }; 575 };
+
+:foreach beep in=$beeps do={
+ :if ([ :len $beep ] = 2) do={
+ :beep frequency=[ :pick $beep 0 ] length=([ :pick $beep 1 ] . "ms");
+ } else={
+ :delay ($beep . "ms");
+ }
+}
diff --git a/update-gre-address b/update-gre-address
new file mode 100644
index 0000000..ea55a9b
--- /dev/null
+++ b/update-gre-address
@@ -0,0 +1,30 @@
+# RouterOS script: update-gre-address
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+#
+# update gre interface remote address with dynamic address from
+# ipsec remote peer
+
+:global "gre-cert-prefix";
+:global "gre-int-prefix";
+
+/ interface gre set remote-address=0.0.0.0 disabled=yes [ find where !running !disabled ];
+
+:foreach peer in=[ / ip ipsec remote-peers find ] do={
+ :local id [ / ip ipsec remote-peers get $peer id ];
+
+ :if ([ :pick $id 0 [ :len $"gre-cert-prefix" ] ] = $"gre-cert-prefix") do={
+ :local name [ :pick $id [ :len $"gre-cert-prefix" ] [ :len $id ] ];
+ :local addrnew [ / ip ipsec remote-peers get $peer dynamic-address ];
+ :local grename ($"gre-int-prefix" . $name);
+ :local greint [ / interface gre find where name=$grename ];
+ :if ([ :len $greint ] > 0) do={
+ :local addrold [ / interface gre get $greint remote-address ];
+ :local disabled [ / interface gre get $greint disabled ];
+ :if ($addrnew != $addrold || $disabled = true) do={
+ :log info ("Update remote address for interface " . $grename . " to " . $addrnew);
+ / interface gre set remote-address=0.0.0.0 disabled=yes [ find where remote-address=$addrnew name!=$grename ];
+ / interface gre set $greint remote-address=$addrnew disabled=no;
+ }
+ }
+ }
+}
diff --git a/update-tunnelbroker b/update-tunnelbroker
new file mode 100644
index 0000000..cce2c0c
--- /dev/null
+++ b/update-tunnelbroker
@@ -0,0 +1,30 @@
+# RouterOS script: update-tunnelbroker
+# Copyright (c) 2013-2018 Christian Hesse <mail@eworm.de>
+
+:local tunnelurl "ipv4.tunnelbroker.net";
+:local tunneluser "user";
+:local tunnelpass "v3ry-s3cr3t";
+:local tunnelid "user-XXX.tunnel.tserv6.fra1.ipv6.he.net";
+
+# name of the local tunnel interface
+:local tunnelint "tunnelbroker";
+
+# get the last ip address from tunnel interface
+:local tunnellastip [ / interface 6to4 get [ / interface 6to4 find where name=$tunnelint ] local-address ];
+
+# Get the current ip address on interface with default route
+:local tunnelip [ / ip route get [ / ip route find where gateway=[ / ip route get [ / ip route find where dynamic=yes and dst-address="0.0.0.0/0" dynamic active=yes ] gateway ] dst-address!="0.0.0.0/0" ] pref-src ];
+
+# Did we get an IP address to compare?
+:if ([ :typeof $tunnelip ] = nil) do={
+ :log warning ("No default route? Could not get address, please check.");
+} else={
+ :if ($tunnelip != $tunnellastip) do={
+ :log info ("Local address changed, sending UPDATE to tunnelbroker! New address: " . $tunnelip);
+ / tool fetch mode=https address=$tunnelurl user=$tunneluser password=$tunnelpass \
+ src-path=("/nic/update\?hostname=" . $tunnelid) keep-result=no;
+ / interface 6to4 set [ / interface 6to4 find where name=$tunnelint ] local-address=$tunnelip;
+ } else={
+ :log debug "All tunnelbroker configuration is up to date.";
+ }
+}