Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # 2024-01-16 17:49:15 by RouterOS 7.13.2
- # software id = A93J-ZXMT
- #
- # model = C53UiG+5HPaxD2HPaxD
- # serial number = HER09FWBYE6
- /disk
- set usb1 type=hardware
- add parent=usb1 partition-number=1 partition-offset=512 partition-size=\
- "7 763 656 192" type=partition
- /interface bridge
- add arp=proxy-arp name=bridge-lan port-cost-mode=short
- /interface ethernet
- set [ find default-name=ether2 ] arp=local-proxy-arp
- /interface wifi
- set [ find default-name=wifi2 ] channel.band=2ghz-ax .skip-dfs-channels=\
- 10min-cac .width=20/40mhz configuration.country=Russia .mode=ap .ssid=\
- /dev/null .tx-chains="" datapath.bridge=bridge-lan disabled=no mtu=1500 \
- security.authentication-types=wpa2-psk,wpa3-psk .disable-pmkid=yes .ft=\
- yes .ft-over-ds=yes .group-key-update=1h .management-protection=allowed
- /interface wireguard
- add comment=WB listen-port=13333 mtu=1420 name=WB
- add listen-port=13256 mtu=1420 name=WireguardHome
- add listen-port=13331 mtu=1420 name=wireguard-alpina
- add comment="FineVPN interface" listen-port=51820 mtu=1420 name=wireguard2
- add listen-port=13232 mtu=1420 name=wireguard2ccc
- /interface vlan
- add interface=bridge-lan name=bridge.2 vlan-id=1002
- add disabled=yes interface=bridge-lan name=vlan1000 vlan-id=1000
- /interface pppoe-client
- add add-default-route=yes disabled=no interface=ether1 keepalive-timeout=\
- disabled name=vrn.tv user=ripab238
- /interface list
- add include=all name=WAN-LIST
- add name=LAN-LIST
- /ip dhcp-server option
- add code=42 name="NTP Server" value="'192.168.254.1'"
- add code=119 name=Domain_Search_value value="'DUNE.ZONE'"
- add code=15 name="Domain_Name value" value="'DUNE.ZONE'"
- add code=66 name=pxe value="'192.168.254.5'"
- add code=6 name=YandexDNS value="'77.88.8.7'"
- /ip pool
- add name=dhcp_pool0 ranges=192.168.254.25-192.168.254.229
- add name=dhcp2-pool ranges=192.168.154.0/24
- add name=dhcp_pool2 ranges=192.168.154.2-192.168.154.254
- /ip dhcp-server
- add add-arp=yes address-pool=dhcp_pool0 comment="domain=dune.zone" interface=\
- bridge-lan lease-script="# MikroTik (RouterOS) script for automatically se\
- tting DNS records\r\
- \n# for clients when they obtain a DHCP lease.\r\
- \n#\r\
- \n# author SmartFinn <https://gist.github.com/SmartFinn>\r\
- \n\r\
- \n:local dnsTTL \"00:15:00\";\r\
- \n:local token \"\$leaseServerName-\$leaseActMAC\";\r\
- \n\r\
- \n# Normalize hostname (e.g. \"-= My Phone =-\" -> \"My-Phone\")\r\
- \n# - truncate length to 63 chars\r\
- \n# - substitute disallowed chars with a hyphen\r\
- \n# param: name\r\
- \n:local normalizeHostname do={\r\
- \n :local result;\r\
- \n :local isInvalidChar true;\r\
- \n :for i from=0 to=([:len \$name]-1) do={\r\
- \n :local char [:pick \$name \$i];\r\
- \n :if (\$i < 63) do={\r\
- \n :if (\$char~\"[a-zA-Z0-9]\") do={\r\
- \n :set result (\$result . \$char);\r\
- \n :set isInvalidChar false;\r\
- \n } else={\r\
- \n :if (!\$isInvalidChar) do={\r\
- \n :set result (\$result . \"-\");\r\
- \n :set isInvalidChar true;\r\
- \n };\r\
- \n };\r\
- \n };\r\
- \n };\r\
- \n# delete trailing hyphen\r\
- \n :if (\$isInvalidChar) do={\r\
- \n :set result [:pick \$result 0 ([:len \$result]-1)];\r\
- \n }\r\
- \n :return \$result;\r\
- \n};\r\
- \n\r\
- \n:if (\$leaseBound = 1) do={\r\
- \n# Getting the hostname and delete all disallowed chars from it\r\
- \n :local hostName \$\"lease-hostname\";\r\
- \n :set hostName [\$normalizeHostname name=\$hostName];\r\
- \n\r\
- \n# Use MAC address as a hostname if the hostname is missing or contains o\
- nly\r\
- \n# disallowed chars\r\
- \n :if ([:len \$hostName] = 0) do={\r\
- \n :set hostName [\$normalizeHostname name=\$leaseActMAC];\r\
- \n };\r\
- \n\r\
- \n# Getting the domain name from DHCP server. If a domain name is not\r\
- \n# specified will use hostname only\r\
- \n /ip dhcp-server network {\r\
- \n :local domainName [get [:pick [find \$leaseActIP in address] 0] doma\
- in];\r\
- \n :if ([:len \$domainName] > 0) do={\r\
- \n# Append domain name to the hostname\r\
- \n :set hostName (\$hostName . \".\" . \$domainName);\r\
- \n };\r\
- \n };\r\
- \n\r\
- \n :do {\r\
- \n /ip dns static {\r\
- \n add name=\$hostName address=\$leaseActIP ttl=\$dnsTTL comment=\$to\
- ken;\r\
- \n };\r\
- \n } on-error={\r\
- \n :log error \"Fail to add DNS entry: \$hostname -> \$leaseActIP (\$le\
- aseActMAC)\";\r\
- \n };\r\
- \n} else={\r\
- \n /ip dns static remove [find comment=\$token];\r\
- \n};" name=dhcp1
- add add-arp=yes address-pool=dhcp_pool2 interface=bridge.2 name=dhcp2
- /ppp profile
- set *0 change-tcp-mss=no
- /routing table
- add fib name=tovpn
- /routing bgp template
- set default disabled=no routing-table=main
- add as=64999 disabled=no name=antifilter output.network=bgp-networks \
- .no-client-to-client-reflection=yes router-id=46.72.222.7 routing-table=\
- main
- /snmp community
- set [ find default=yes ] addresses=95.142.47.131/32
- /system logging action
- add disk-file-count=10 disk-file-name=usb1-part1/logs/info-log- \
- disk-lines-per-file=5000 name=USBinfo target=disk
- /user group
- add name=prometheus policy="local,telnet,ssh,ftp,reboot,read,write,policy,test\
- ,winbox,password,web,sniff,sensitive,api,romon,rest-api"
- /interface bridge filter
- add action=drop chain=output mac-protocol=ip out-interface=ether2 \
- packet-type=multicast
- /interface bridge port
- add bridge=bridge-lan interface=LAN-LIST internal-path-cost=10 path-cost=10
- /ip neighbor discovery-settings
- set protocol=""
- /interface bridge vlan
- add bridge=bridge-lan tagged=bridge-lan,ether5 vlan-ids=1002
- /interface detect-internet
- set lan-interface-list=LAN-LIST wan-interface-list=WAN-LIST
- /interface list member
- add interface=ether2 list=LAN-LIST
- add interface=ether3 list=LAN-LIST
- add interface=vrn.tv list=WAN-LIST
- add interface=bridge-lan list=LAN-LIST
- add interface=ether1 list=WAN-LIST
- add interface=ether5 list=LAN-LIST
- add interface=wireguard2 list=LAN-LIST
- add interface=wireguard-alpina list=LAN-LIST
- add interface=wireguard2ccc list=LAN-LIST
- add interface=WB list=LAN-LIST
- /interface wireguard peers
- add allowed-address=0.0.0.0/0 endpoint-address=ru2.wg.finevpn.org \
- endpoint-port=993 interface=wireguard2 persistent-keepalive=21s \
- public-key="WMo4krc0Wsi/Pz9rPBQLL38Os8erB+DfSKN4rteUCUU="
- add allowed-address=10.10.24.0/30,192.168.240.0/24 endpoint-address=\
- 178.210.48.232 endpoint-port=13331 interface=wireguard-alpina \
- persistent-keepalive=5h47m44s public-key=\
- "1IxAnKghKVR2Q9x0nBBnZx38Ve9LD7Cv6Iif2Cb2Ih0="
- add allowed-address=\
- 10.0.0.0/8,192.168.254.38/32,192.168.254.227/32,192.168.254.250/32 \
- comment=wildberries endpoint-address=wg.wb.ru endpoint-port=443 \
- interface=WB persistent-keepalive=15s preshared-key=\
- "mBOt3pKkHwuG/q+E5eY2te1G1eYxYiz4yk7mJm/6LBM=" public-key=\
- "5rZ+nLz9+O874sw/rgUX3G/0qLiKseYpniUDqC4KYBI="
- add allowed-address=10.100.100.3/24 interface=WireguardHome \
- persistent-keepalive=21s public-key=\
- "qHDLG+wVopUbLqjjVPxTa1zdABtu9DH5z4N1z5HTkx0="
- add allowed-address=10.100.100.0/24 disabled=yes interface=WireguardHome \
- persistent-keepalive=21s public-key=\
- "+83afkd7kpwKED1qYe1vOBhHtorFjCxm4MFInDtcRnU="
- add allowed-address=10.10.10.0/23,192.168.1.0/24 endpoint-address=\
- vusc.softether.net endpoint-port=13232 interface=wireguard2ccc \
- persistent-keepalive=21s public-key=\
- "s3vTV5fgdUbQdCAaxSMCg31QNKxcifNa3ayQAKcx618="
- /ip address
- add address=192.168.254.1/24 interface=bridge-lan network=192.168.254.0
- add address=10.22.138.251 interface=wireguard2 network=10.22.138.251
- add address=10.9.34.187/16 disabled=yes interface=wireguard2ccc network=\
- 10.9.0.0
- add address=10.10.10.2/23 interface=wireguard2ccc network=10.10.10.0
- add address=10.10.24.2/30 interface=wireguard-alpina network=10.10.24.0
- add address=10.20.100.109 interface=WB network=10.20.100.109
- add address=10.100.100.1/24 interface=WireguardHome network=10.100.100.0
- add address=192.168.154.1/24 interface=bridge.2 network=192.168.154.0
- /ip dhcp-client
- add disabled=yes interface=ether1 use-peer-dns=no
- /ip dhcp-server alert
- add disabled=no interface=bridge-lan
- /ip dhcp-server lease
- add address=192.168.254.13 client-id=SubWoofer comment="hostname=SubWoofer" \
- mac-address=10:D5:61:D4:70:B6 server=dhcp1
- add address=192.168.254.10 client-id=Bathroom1 comment="hostname=Bathroom1" \
- mac-address=10:D5:61:D4:7F:CC server=dhcp1
- add address=192.168.254.11 client-id=Bathroom2 comment="hostname=Bathroom2" \
- mac-address=10:D5:61:D4:79:07 server=dhcp1
- add address=192.168.254.118 client-id=ZigBee-Gateway comment=\
- "hostname=ZigBee-Gateway" mac-address=10:D5:61:20:4A:03 server=dhcp1
- add address=192.168.254.16 client-id=ff:6e:5e:65:a8:0:3:0:1:b8:87:6e:5e:65:a8 \
- mac-address=B8:87:6E:5E:65:A8 server=dhcp1
- add address=192.168.254.12 client-id=Bathroom3 comment="hostname=Bathroom3" \
- mac-address=10:D5:61:D4:84:74 server=dhcp1
- add address=192.168.254.15 client-id=1:ac:64:cf:a7:b0:4d comment=\
- "hostname=MiRobot" mac-address=AC:64:CF:A7:B0:4D server=dhcp1
- add address=192.168.254.3 client-id=1:8:55:31:e4:7d:23 mac-address=\
- 08:55:31:E4:7D:23 server=dhcp1
- add address=192.168.254.2 client-id=1:ac:15:a2:2:b1:34 comment=\
- "hostname=TL-SG108E" mac-address=AC:15:A2:02:B1:34 server=dhcp1
- add address=192.168.254.14 client-id=ff:6e:18:66:1b:0:3:0:1:b8:87:6e:18:66:1b \
- mac-address=B8:87:6E:18:66:1B server=dhcp1
- add address=192.168.254.17 client-id=1:6c:d:c4:f4:ca:14 comment=\
- "hostname=MITV" mac-address=6C:0D:C4:F4:CA:14 server=dhcp1
- add address=192.168.254.20 client-id=SmartSocketTV comment=\
- "hostname=SmartSocketTV" mac-address=1C:90:FF:59:A4:06 server=dhcp1
- add address=192.168.254.18 client-id=SmartSocketWC comment=\
- "hostname=SmartSocketWC" mac-address=1C:90:FF:5A:77:82 server=dhcp1
- add address=192.168.254.38 comment="hostname=LieT-PC" mac-address=\
- 9C:6B:00:16:C1:CF server=dhcp1
- add address=192.168.254.5 client-id=1:d8:38:d:3c:d6:30 comment=\
- "hostname=Wi-Fi AP" mac-address=D8:38:0D:3C:D6:30 server=dhcp1
- add address=192.168.154.26 client-id=Gree comment=AC mac-address=\
- 78:0F:77:30:C9:DD server=dhcp2
- add address=192.168.254.29 client-id=1:c2:40:f9:ef:3c:1c comment=\
- "hostname=HonorView20" mac-address=C2:40:F9:EF:3C:1C server=dhcp1
- add address=192.168.254.27 client-id=1:c8:4d:44:20:1c:b7 comment=\
- "hostname=MiBox" mac-address=C8:4D:44:20:1C:B7 server=dhcp1
- add address=192.168.254.250 client-id=\
- ff:8a:e0:28:80:0:2:0:0:ab:11:a2:be:d1:6b:a7:81:9c:1d comment=\
- "hostname=rockpi" mac-address=00:E0:4C:03:01:57 server=dhcp1
- add address=192.168.254.54 comment="hostname=HUMIDIFIER" mac-address=\
- EC:4D:3E:83:C6:C7 server=dhcp1
- add address=192.168.254.56 comment="hostname=Humidity_sensor_bathroom" \
- mac-address=FC:67:1F:E3:74:3A server=dhcp1
- add address=192.168.154.49 client-id=1:c0:84:7d:1f:3a:46 comment=\
- "hostname=Yandex.StationRED" mac-address=C0:84:7D:1F:3A:46 server=dhcp2
- add address=192.168.254.35 client-id=1:4c:ab:4f:c6:2b:6c comment=\
- "hostname=iPhone-Anna" mac-address=4C:AB:4F:C6:2B:6C server=dhcp1
- add address=192.168.254.227 client-id=1:5c:ed:f4:a0:17:80 comment=\
- "hostname=LieT-S22" mac-address=5C:ED:F4:A0:17:80 server=dhcp1
- add address=192.168.154.4 comment="hostname=HUMIDIFIER2" mac-address=\
- 7C:C2:94:26:96:E5 server=dhcp2
- add address=192.168.154.8 comment="hostname=HUMIDIFIER" mac-address=\
- EC:4D:3E:83:C6:C7 server=dhcp2
- add address=192.168.154.10 client-id=\
- ff:6e:18:66:1b:0:1:0:1:2d:20:2e:59:b8:87:6e:18:66:1b mac-address=\
- B8:87:6E:18:66:1B server=dhcp2
- add address=192.168.154.13 client-id=\
- ff:6e:5e:65:a8:0:1:0:1:c7:92:bc:8b:b8:87:6e:5e:65:a8 mac-address=\
- B8:87:6E:5E:65:A8 server=dhcp2
- /ip dhcp-server network
- add address=192.168.154.0/24 dns-server=192.168.254.250 gateway=192.168.154.1 \
- netmask=24
- add address=192.168.254.0/24 dns-server=192.168.254.250 gateway=192.168.254.1 \
- ntp-server=192.168.254.1
- /ip dns
- set cache-max-ttl=1s cache-size=1024KiB max-concurrent-queries=1000 \
- max-concurrent-tcp-sessions=700 max-udp-packet-size=1800 \
- query-server-timeout=1s query-total-timeout=3s servers=192.168.254.250 \
- use-doh-server=https://main.mentat.su/dns-query verify-doh-cert=yes
- /ip dns static
- add forward-to=10.15.12.200 regexp="^.*(\\.|^)wb\\.ru\\.\?\$" type=FWD
- add address=93.115.24.204 comment=\
- "https://dns.comss.one/dns-query 93.115.24.204 93.115.24.205" name=\
- dns.comss.one
- add address=93.115.24.205 disabled=yes name=dns.comss.one
- add address=45.91.92.121 disabled=yes name=doh-ch.blahdns.com
- add address=45.90.28.199 comment=\
- https://dns.nextdns.io/cdd1f6/Mikrotik%20hAP3 disabled=yes name=\
- dns.nextdns.io
- add address=45.90.30.199 disabled=yes name=dns.nextdns.io
- add address=2a07:a8c0:: disabled=yes name=dns.nextdns.io type=AAAA
- add address=2a07:a8c1:: disabled=yes name=dns.nextdns.io type=AAAA
- add address=185.199.111.153 disabled=yes name=lampa.mx
- add address=94.140.14.49 comment=https://72984969.d.adguard-dns.com/dns-query \
- disabled=yes name=72984969.d.adguard-dns.com
- add address=94.140.14.59 comment=https://72984969.d.adguard-dns.com/dns-query \
- disabled=yes name=72984969.d.adguard-dns.com
- add comment=OpenNIC disabled=yes forward-to=\
- 185.121.177.177,169.239.202.202,2a05:dfc7:5::53::1,2a05:dfc7:5::5353::1 \
- regexp=".*(\\.bbs|\\.chan|\\.cyb|\\.dyn|\\.geek|\\.gopher|\\.indy|\\.libre\
- |\\.neo|\\.null|\\.o)\$" type=FWD
- add comment=OpenNIC forward-to=\
- 185.121.177.177,169.239.202.202,2a05:dfc7:5::53::1,2a05:dfc7:5::5353::1 \
- regexp=".*(\\.oss|\\.oz|\\.parody|\\.pirate|\\.opennic.glue|\\.dns\\.openn\
- ic\\.glue)\$" type=FWD
- add address=192.168.254.250 comment=\
- "managed by dhcp-to-dns, macaddress=00:E0:4C:03:01:57, server=dhcp1" \
- name=00-E0-4C-03-01-57.dune.local ttl=5m
- add cname=00-E0-4C-03-01-57.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=00:E0:4C:03:01:57, server=dhcp1" \
- name=rockpi.dune.local ttl=5m type=CNAME
- add address=192.168.254.2 comment=\
- "managed by dhcp-to-dns, macaddress=AC:15:A2:02:B1:34, server=dhcp1" \
- name=AC-15-A2-02-B1-34.dune.local ttl=5m
- add cname=AC-15-A2-02-B1-34.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=AC:15:A2:02:B1:34, server=dhcp1" \
- name=TL-SG108E.dune.local ttl=5m type=CNAME
- add address=192.168.254.13 comment=\
- "managed by dhcp-to-dns, macaddress=10:D5:61:D4:70:B6, server=dhcp1" \
- name=10-D5-61-D4-70-B6.dune.local ttl=5m
- add cname=10-D5-61-D4-70-B6.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=10:D5:61:D4:70:B6, server=dhcp1" \
- name=SubWoofer.dune.local ttl=5m type=CNAME
- add address=192.168.254.51 comment=\
- "managed by dhcp-to-dns, macaddress=1C:90:FF:58:97:A6, server=dhcp1" \
- name=1C-90-FF-58-97-A6.dune.local ttl=5m
- add cname=1C-90-FF-58-97-A6.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=1C:90:FF:58:97:A6, server=dhcp1" \
- name=wlan0.dune.local ttl=5m type=CNAME
- add address=192.168.154.2 comment=\
- "managed by dhcp-to-dns, macaddress=1C:90:FF:59:A4:06, server=dhcp2" \
- name=1C-90-FF-59-A4-06.dune.local ttl=5m
- add address=192.168.154.3 comment=\
- "managed by dhcp-to-dns, macaddress=10:D5:61:D4:79:07, server=dhcp2" \
- name=10-D5-61-D4-79-07.dune.local ttl=5m
- add address=192.168.154.4 comment=\
- "managed by dhcp-to-dns, macaddress=7C:C2:94:26:96:E5, server=dhcp2" \
- name=7C-C2-94-26-96-E5.dune.local ttl=5m
- add address=192.168.154.5 comment=\
- "managed by dhcp-to-dns, macaddress=10:D5:61:D4:84:74, server=dhcp2" \
- name=10-D5-61-D4-84-74.dune.local ttl=5m
- add address=192.168.154.7 comment=\
- "managed by dhcp-to-dns, macaddress=10:D5:61:D4:7F:CC, server=dhcp2" \
- name=10-D5-61-D4-7F-CC.dune.local ttl=5m
- add address=192.168.154.8 comment=\
- "managed by dhcp-to-dns, macaddress=EC:4D:3E:83:C6:C7, server=dhcp2" \
- name=EC-4D-3E-83-C6-C7.dune.local ttl=5m
- add address=192.168.154.9 comment=\
- "managed by dhcp-to-dns, macaddress=FC:67:1F:5A:FB:4E, server=dhcp2" \
- name=FC-67-1F-5A-FB-4E.dune.local ttl=5m
- add address=192.168.154.10 comment=\
- "managed by dhcp-to-dns, macaddress=B8:87:6E:18:66:1B, server=dhcp2" \
- name=B8-87-6E-18-66-1B.dune.local ttl=5m
- add cname=B8-87-6E-18-66-1B.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=B8:87:6E:18:66:1B, server=dhcp2" \
- name=yandex-mini2.dune.local ttl=5m type=CNAME
- add address=192.168.254.38 comment=\
- "managed by dhcp-to-dns, macaddress=9C:6B:00:16:C1:CF, server=dhcp1" \
- name=9C-6B-00-16-C1-CF.dune.local ttl=5m
- add cname=9C-6B-00-16-C1-CF.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=9C:6B:00:16:C1:CF, server=dhcp1" \
- name=LieT-PC.dune.local ttl=5m type=CNAME
- add cname=7C-C2-94-26-96-E5.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=7C:C2:94:26:96:E5, server=dhcp2" \
- name=HUMIDIFIER2.dune.local ttl=5m type=CNAME
- add cname=EC-4D-3E-83-C6-C7.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=EC:4D:3E:83:C6:C7, server=dhcp2" \
- name=HUMIDIFIER.dune.local ttl=5m type=CNAME
- add address=192.168.154.49 comment=\
- "managed by dhcp-to-dns, macaddress=C0:84:7D:1F:3A:46, server=dhcp2" \
- name=C0-84-7D-1F-3A-46.dune.local ttl=5m
- add cname=C0-84-7D-1F-3A-46.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=C0:84:7D:1F:3A:46, server=dhcp2" \
- name=Yandex.StationRED.dune.local ttl=5m type=CNAME
- add address=192.168.254.5 comment=\
- "managed by dhcp-to-dns, macaddress=D8:38:0D:3C:D6:30, server=dhcp1" \
- name=D8-38-0D-3C-D6-30.dune.local ttl=5m
- add cname=D8-38-0D-3C-D6-30.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=D8:38:0D:3C:D6:30, server=dhcp1" \
- name=Wi-FiAP.dune.local ttl=5m type=CNAME
- add address=192.168.254.28 comment=\
- "managed by dhcp-to-dns, macaddress=78:4F:43:43:FF:96, server=dhcp1" \
- name=78-4F-43-43-FF-96.dune.local ttl=5m
- add cname=78-4F-43-43-FF-96.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=78:4F:43:43:FF:96, server=dhcp1" \
- name=iPhone-Mihail.dune.local ttl=5m type=CNAME
- add address=192.168.254.35 comment=\
- "managed by dhcp-to-dns, macaddress=4C:AB:4F:C6:2B:6C, server=dhcp1" \
- name=4C-AB-4F-C6-2B-6C.dune.local ttl=5m
- add cname=4C-AB-4F-C6-2B-6C.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=4C:AB:4F:C6:2B:6C, server=dhcp1" \
- name=iPhone-Anna.dune.local ttl=5m type=CNAME
- add address=192.168.154.13 comment=\
- "managed by dhcp-to-dns, macaddress=B8:87:6E:5E:65:A8, server=dhcp2" \
- name=B8-87-6E-5E-65-A8.dune.local ttl=5m
- add cname=B8-87-6E-5E-65-A8.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=B8:87:6E:5E:65:A8, server=dhcp2" \
- name=Yandex-Station-gen2.dune.local ttl=5m type=CNAME
- add address=192.168.154.6 comment=\
- "managed by dhcp-to-dns, macaddress=3A:C9:E8:0D:A7:5D, server=dhcp2" \
- name=3A-C9-E8-0D-A7-5D.dune.local ttl=5m
- add cname=3A-C9-E8-0D-A7-5D.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=3A:C9:E8:0D:A7:5D, server=dhcp2" \
- name=LieT-S22.dune.local ttl=5m type=CNAME
- add address=192.168.254.17 comment=\
- "managed by dhcp-to-dns, macaddress=6C:0D:C4:F4:CA:14, server=dhcp1" \
- name=6C-0D-C4-F4-CA-14.dune.local ttl=5m
- add cname=6C-0D-C4-F4-CA-14.dune.local comment=\
- "managed by dhcp-to-dns, macaddress=6C:0D:C4:F4:CA:14, server=dhcp1" \
- name=MITV.dune.local ttl=5m type=CNAME
- add comment="--- dhcp-to-dns above ---" disabled=yes name=- type=NXDOMAIN
- add address=104.20.91.49 disabled=yes name=auth.adguard.com
- add address=95.142.47.131 comment=https://main.mentat.su/dns-query name=\
- monitoring.mentat.su
- add address=192.168.254.250 name=main.mentat.su
- add address=1.1.1.1 name=dns.cloudflare.com
- add address=1.0.0.1 name=dns.cloudflare.com
- add address=2606:4700:4700::1111 comment=https://1.1.1.1/dns-query name=\
- dns.cloudflare.com type=AAAA
- add address=2606:4700:4700::1001 name=dns.cloudflare.com type=AAAA
- add address=10.15.12.100 comment=111 disabled=yes regexp=".*.wb\\.ru\$"
- add disabled=yes forward-to=10.15.12.200 match-subdomain=yes name=wb.ru type=\
- FWD
- add address=8.8.8.8 name=dns.google
- add address=91.230.107.85 name=wg.wb.ru
- add forward-to=10.15.12.200 regexp=".*\\.wb.\\ru" type=FWD
- add forward-to=10.15.12.200 regexp=" \\.wb\\.ru\$" type=FWD
- add forward-to=10.15.12.200 regexp=".*wb\\.ru" type=FWD
- add address=192.168.254.26 comment=dhcp1-78:0F:77:30:C9:DD name=BL-30-c9-dd \
- ttl=15m
- add address=192.168.254.38 comment=dhcp1-9C:6B:00:16:C1:CF name=LieT-PC ttl=\
- 15m
- add address=192.168.254.2 comment=dhcp1-AC:15:A2:02:B1:34 name=TL-SG108E ttl=\
- 15m
- add address=192.168.254.5 comment=dhcp1-D8:38:0D:3C:D6:30 name=\
- linux-30d63c0d38d8 ttl=15m
- add address=192.168.254.28 comment=dhcp1-78:4F:43:43:FF:96 name=iPhone-Mihail \
- ttl=15m
- add address=192.168.254.250 comment=dhcp1-00:E0:4C:03:01:57 name=rockpi ttl=\
- 15m
- add address=192.168.254.51 comment=dhcp1-1C:90:FF:58:97:A6 name=wlan0 ttl=15m
- add address=192.168.254.35 comment=dhcp1-4C:AB:4F:C6:2B:6C name=iPhone-Anna \
- ttl=15m
- add address=192.168.254.13 comment=dhcp1-10:D5:61:D4:70:B6 name=wlan0 ttl=15m
- add address=192.168.254.17 comment=dhcp1-6C:0D:C4:F4:CA:14 name=MITV ttl=15m
- /ip firewall address-list
- add address=192.168.254.0/24 list=LOCAL_LAN
- add address=atredes.rostelekom.xyz list=Route2Force_vrn.tv
- add address=192.168.254.20 list=S22
- add address=192.168.254.21 list=S22
- add address=192.168.240.0/24 list=ALLOWED_NETWORKS
- add address=192.168.1.0/24 list=ALLOWED_NETWORKS
- add address=10.10.10.0/30 list=ALLOWED_NETWORKS
- add address=10.20.89.70 list=ALLOWED_NETWORKS
- add address=10.10.24.0/30 list=ALLOWED_NETWORKS
- add address=192.168.254.0/24 list=LAN+WIFI
- add address=192.168.3.0/24 list=LAN+WIFI
- add address=192.168.254.250 list=2-WB
- add address=192.168.254.38 list=2-WB
- add address=192.168.254.227 list=2-WB
- add address=93.189.48.0/21 list=Tele2
- add address=176.59.0.0/19 list=Tele2
- add address=217.169.82.0/23 list=Tele2
- add address=217.169.84.0/22 list=Tele2
- add address=217.169.88.0/21 list=Tele2
- add address=10.15.12.100 list=ExcludeDNSForward
- add address=0.0.0.0/8 comment=RFC6890 list=not_in_internet
- add address=172.16.0.0/12 comment=RFC6890 list=not_in_internet
- add address=192.168.0.0/16 comment=RFC6890 list=not_in_internet
- add address=10.0.0.0/8 comment=RFC6890 list=not_in_internet
- add address=169.254.0.0/16 comment=RFC6890 list=not_in_internet
- add address=127.0.0.0/8 comment=RFC6890 list=not_in_internet
- add address=224.0.0.0/4 comment=Multicast list=not_in_internet
- add address=198.18.0.0/15 comment=RFC6890 list=not_in_internet
- add address=192.0.0.0/24 comment=RFC6890 list=not_in_internet
- add address=192.0.2.0/24 comment=RFC6890 list=not_in_internet
- add address=198.51.100.0/24 comment=RFC6890 list=not_in_internet
- add address=203.0.113.0/24 comment=RFC6890 list=not_in_internet
- add address=100.64.0.0/10 comment=RFC6890 list=not_in_internet
- add address=240.0.0.0/4 comment=RFC6890 list=not_in_internet
- add address=192.88.99.0/24 comment="6to4 relay Anycast [RFC 3068]" list=\
- not_in_internet
- add address=192.168.154.0/24 list=LOCAL_LAN
- /ip firewall filter
- add action=drop chain=input comment=Invalid-DROP connection-state=invalid \
- log-prefix=Invalid
- add action=drop chain=forward comment=\
- "Drop packets from LAN that do not have LAN IP" in-interface=bridge-lan \
- log=yes log-prefix=LAN_!LAN src-address-list=!LOCAL_LAN
- add action=drop chain=forward comment=\
- "Drop incoming packets that are not NAT`ted" connection-nat-state=!dstnat \
- connection-state=new in-interface=vrn.tv log=yes log-prefix=!NAT
- add action=drop chain=forward comment=\
- "Drop incoming from internet which is not public IP" in-interface=vrn.tv \
- log=yes log-prefix=!public src-address-list=not_in_internet
- add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \
- connection-state=established,related hw-offload=yes in-interface=\
- bridge-lan out-interface-list=WAN-LIST
- add action=fasttrack-connection chain=forward comment=\
- "111111111defconf: fasttrack" connection-state=established,related \
- hw-offload=yes in-interface=bridge.2 out-interface-list=WAN-LIST
- add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \
- connection-mark=no-mark connection-state=established,related dst-port=!53 \
- hw-offload=yes in-interface-list=WAN-LIST out-interface=bridge-lan \
- protocol=udp
- add action=fasttrack-connection chain=forward comment=\
- "111111defconf: fasttrack" connection-mark=no-mark connection-state=\
- established,related dst-port=!53 hw-offload=yes in-interface-list=\
- WAN-LIST out-interface=bridge.2 protocol=udp
- add action=accept chain=input comment="allow wireguard" dst-port=13256 \
- protocol=udp
- add action=accept chain=forward dst-address-list=LOCAL_LAN src-address-list=\
- LOCAL_LAN
- add action=drop chain=output disabled=yes log-prefix=RST protocol=tcp \
- tcp-flags=rst
- add action=drop chain=input comment="dns block" dst-port=53,853,5353 \
- log-prefix="DNS BLOCK" protocol=udp src-address-list=!LOCAL_LAN
- add action=accept chain=input comment="Accept All DEBUG" disabled=yes \
- log-prefix="ALLOW ALL DEBUG"
- add action=accept chain=forward comment="Accept All DEBUG" disabled=yes \
- log-prefix="ALLOW ALL DEBUG"
- add action=accept chain=input dst-address=10.10.10.0/30 log-prefix=CCC!
- add action=accept chain=input dst-address=192.168.154.0/24 log-prefix=\
- CC23232C!
- add action=accept chain=input dst-address=10.100.100.0/24 log-prefix=CCC! \
- protocol=udp
- add action=accept chain=input comment="DISABLE 14/02" in-interface=\
- wireguard-alpina log=yes log-prefix=alpina
- add action=accept chain=input comment="DISABLE 14/02" in-interface=\
- wireguard2ccc log=yes log-prefix=alpina
- add action=drop chain=input dst-port=53 in-interface-list=WAN-LIST log=yes \
- log-prefix=DROP_DNS_WEB protocol=udp src-address-list=!LOCAL_LAN
- add action=reject chain=forward disabled=yes in-interface=bridge-lan log=yes \
- log-prefix=DROP_NOT_INCOMING_FROM_LAN reject-with=\
- icmp-network-unreachable src-address-list=!LAN+WIFI
- add action=accept chain=input connection-state=established,related,untracked \
- in-interface-list=WAN-LIST
- add action=accept chain=forward comment=\
- "1.1. Forward and Input Established and Related connections" \
- connection-state=established,related,untracked in-interface-list=WAN-LIST
- add action=accept chain=input comment="Allow IGMP" in-interface-list=WAN-LIST \
- protocol=igmp
- add action=accept chain=input comment="Allow LAN Traffic" in-interface-list=\
- LAN-LIST
- add action=accept chain=input disabled=yes dst-port=53 in-interface-list=\
- LAN-LIST protocol=udp
- add action=accept chain=input comment=\
- "Allow Discover in LAN,DISABLE 14/02 zero trafic" disabled=yes \
- in-interface-list=LAN-LIST port=5678 protocol=udp
- add action=accept chain=input comment="Allow SNMP" dst-port=161 \
- in-interface-list=WAN-LIST log-prefix=SNMPF protocol=udp
- add action=accept chain=input comment="Allow API" dst-port=8728 \
- in-interface-list=WAN-LIST log-prefix="API Prometheus" protocol=tcp \
- src-address=95.142.47.131
- add action=accept chain=forward comment=WG dst-port=13256 in-interface-list=\
- WAN-LIST log-prefix=WG protocol=udp src-address=0.0.0.0
- add action=accept chain=input comment="Access Normal Ping" in-interface-list=\
- WAN-LIST limit=50/5s,2:packet protocol=icmp
- add action=add-src-to-address-list address-list="Hacker Scanners" \
- address-list-timeout=4w2d chain=input comment="Port Scanners" \
- in-interface-list=WAN-LIST protocol=tcp psd=21,3s,3,1
- add action=add-src-to-address-list address-list="Hacker Scanners" \
- address-list-timeout=4w2d chain=input comment="NMAP FIN Stealth scan" \
- in-interface-list=WAN-LIST protocol=tcp tcp-flags=\
- fin,!syn,!rst,!psh,!ack,!urg
- add action=add-src-to-address-list address-list="Hacker Scanners" \
- address-list-timeout=4w2d chain=input comment="SYN/FIN scan" \
- in-interface-list=WAN-LIST protocol=tcp tcp-flags=fin,syn
- add action=add-src-to-address-list address-list="Hacker Scanners" \
- address-list-timeout=4w2d chain=input comment="SYN/RST scan" \
- in-interface-list=WAN-LIST protocol=tcp tcp-flags=syn,rst
- add action=add-src-to-address-list address-list="Hacker Scanners" \
- address-list-timeout=4w2d chain=input comment="FIN/PSH/URG scan" \
- in-interface-list=WAN-LIST protocol=tcp tcp-flags=\
- fin,psh,urg,!syn,!rst,!ack
- add action=add-src-to-address-list address-list="Hacker Scanners" \
- address-list-timeout=4w2d chain=input comment="ALL/ALL scan" \
- in-interface-list=WAN-LIST protocol=tcp tcp-flags=fin,syn,rst,psh,ack,urg
- add action=add-src-to-address-list address-list="Hacker Scanners" \
- address-list-timeout=4w2d chain=input comment="NMAP NULL scan" \
- in-interface-list=WAN-LIST protocol=tcp tcp-flags=\
- !fin,!syn,!rst,!psh,!ack,!urg
- add action=add-src-to-address-list address-list="Honeypot Hacker" \
- address-list-timeout=4w2d chain=input comment=\
- "block honeypot ssh rdp winbox" connection-state=new dst-port=\
- 22,3389,8291,25,21,8728 in-interface-list=WAN-LIST protocol=tcp
- add action=drop chain=input comment="drop 8.217.255.5" src-address=\
- 8.217.255.5
- add action=drop chain=forward comment="drop 8.217.255.5" src-address=\
- 8.217.255.5
- add action=drop chain=input comment="Drop All Other" disabled=yes \
- in-interface-list=WAN-LIST log-prefix=DEF_DROP
- /ip firewall mangle
- add action=change-mss chain=forward disabled=yes log=yes log-prefix=\
- CHANGE-MSS-OUT new-mss=clamp-to-pmtu out-interface-list=WAN-LIST \
- passthrough=yes protocol=tcp tcp-flags=syn tcp-mss=1300-65535
- add action=change-mss chain=forward new-mss=1420 out-interface-list=WAN-LIST \
- passthrough=yes protocol=tcp tcp-flags=syn tcp-mss=1421-65535
- add action=change-mss chain=forward in-interface-list=WAN-LIST log-prefix=\
- CHANGE-MSS-OUT new-mss=clamp-to-pmtu passthrough=no protocol=tcp \
- tcp-flags=syn tcp-mss=1300-65535
- add action=mark-connection chain=prerouting comment=DNS-Mark \
- connection-state=new disabled=yes dst-port=53,853,5353 \
- new-connection-mark=via-dns passthrough=yes protocol=tcp src-address=\
- 192.168.254.0/24
- add action=mark-connection chain=prerouting connection-state=new disabled=yes \
- dst-port=53,853,5353 new-connection-mark=via-dns passthrough=yes \
- protocol=udp src-address=192.168.254.0/24
- add action=change-mss chain=forward disabled=yes new-mss=1400 out-interface=\
- WB passthrough=yes protocol=tcp tcp-flags=syn
- /ip firewall nat
- add action=masquerade chain=srcnat comment=TELEKOM-SERVICE dst-address=\
- !192.168.254.0/24 log-prefix=1 out-interface=vrn.tv src-address=\
- 192.168.254.0/24 to-addresses=185.23.83.133
- add action=masquerade chain=srcnat dst-port=!53,853,5353 log-prefix=\
- sdsdsdddsdd protocol=udp src-address=192.168.154.0/24
- add action=masquerade chain=srcnat dst-port=!53,853,5353 log-prefix=\
- sdsdsdddsdd protocol=tcp src-address=192.168.154.0/24
- add action=dst-nat chain=dstnat comment=piholeNAT1 dst-port=53,853,5353 \
- log-prefix="DNS forward" protocol=udp src-address=192.168.154.0/24 \
- to-addresses=192.168.254.250
- add action=dst-nat chain=dstnat comment=piholeNAT1 dst-port=53,853,5353 \
- log-prefix="DNS forward" protocol=tcp src-address=192.168.154.0/24 \
- to-addresses=192.168.254.250
- add action=masquerade chain=srcnat dst-address=192.168.154.0/24 log-prefix=\
- !!!!192.168.154.4 out-interface=bridge.2 src-address=192.168.254.250
- add action=masquerade chain=srcnat disabled=yes dst-address=192.168.154.8 \
- log=yes log-prefix=!!!!192.168.154.8 out-interface=bridge.2 src-address=\
- 192.168.254.250
- add action=masquerade chain=srcnat comment=TELEKOM-SERVICE-IOT dst-address=\
- !192.168.154.0/24 log-prefix=IOT out-interface=vrn.tv src-address=\
- 192.168.154.0/24 to-addresses=185.23.83.133
- add action=dst-nat chain=dstnat comment=piholeNAT2 disabled=yes dst-address=\
- !192.168.254.250 dst-port=53,853,5353 protocol=tcp src-address=\
- !192.168.254.250 to-addresses=192.168.254.250
- add action=masquerade chain=srcnat comment=piholeNAT3 disabled=yes \
- dst-address=192.168.254.250 dst-port=53,853,5353 protocol=udp \
- src-address=192.168.254.0/24
- add action=masquerade chain=srcnat comment=piholeNAT4 disabled=yes \
- dst-address=192.168.254.250 dst-port=53,853,5353 protocol=tcp \
- src-address=192.168.254.0/24
- add action=src-nat chain=srcnat comment=MEGAFON disabled=yes dst-address=\
- !192.168.254.0/24 log-prefix=1 out-interface=ether1 src-address=\
- 192.168.254.0/24 to-addresses=46.72.222.7
- add action=masquerade chain=srcnat log-prefix=!!! out-interface=wireguard2 \
- src-address=192.168.254.0/24
- add action=masquerade chain=srcnat out-interface=wireguard2ccc src-address=\
- 192.168.254.0/24
- add action=src-nat chain=srcnat comment=MAIN_SRCNAT disabled=yes log=yes \
- out-interface=wireguard-alpina to-addresses=10.10.24.1
- add action=masquerade chain=srcnat comment=WB log-prefix=2 out-interface=WB \
- src-address-list=2-WB
- add action=src-nat chain=srcnat comment="NAT 2 CCC" out-interface=\
- wireguard2ccc src-address-list=LOCAL_LAN to-addresses=10.10.10.2
- add action=masquerade chain=srcnat comment="ALPINA CCC" log-prefix=1 \
- out-interface=wireguard-alpina src-address=192.168.254.0/24
- add action=masquerade chain=srcnat comment=" CCC" log-prefix=1 out-interface=\
- wireguard2ccc src-address=192.168.254.0/24
- add action=masquerade chain=srcnat comment="MASQL CCC" dst-address=\
- 10.10.10.0/23 dst-address-list="" log=yes log-prefix=1
- add action=dst-nat chain=dstnat comment=DNS-QUIC-S22 disabled=yes \
- dst-address=185.23.83.133 dst-port=853 log=yes log-prefix=S22 protocol=\
- tcp to-addresses=192.168.254.250 to-ports=853
- add action=masquerade chain=srcnat disabled=yes out-interface=vrn.tv \
- src-address=192.168.254.0/24
- add action=src-nat chain=srcnat src-address=10.2.0.2 to-addresses=\
- 192.168.254.1
- add action=redirect chain=dstnat comment="Make Mikrotik preferred dns server" \
- disabled=yes dst-port=53,853,5353 in-interface=bridge-lan log-prefix=\
- DNS_FWD_UDP protocol=udp to-addresses=192.168.254.1 to-ports=53
- add action=redirect chain=dstnat comment="Make Mikrotik preferred dns server" \
- disabled=yes dst-port=53,853,5353 in-interface=bridge-lan log-prefix=\
- DNS_FWD_TCP protocol=tcp src-address-list=!S22 to-addresses=192.168.254.1 \
- to-ports=53
- add action=dst-nat chain=dstnat dst-address=185.23.83.133 dst-port=8729 \
- in-interface-list=WAN-LIST log-prefix=AP-API protocol=tcp to-addresses=\
- 192.168.254.19 to-ports=8728
- add action=dst-nat chain=dstnat comment=Prometheus2Router dst-address=\
- 185.23.83.133 dst-port=8729 in-interface-list=WAN-LIST log-prefix=AP-API \
- protocol=tcp to-addresses=192.168.254.1 to-ports=8728
- add action=dst-nat chain=dstnat dst-address=185.23.83.133 dst-port=9221 \
- protocol=tcp to-addresses=192.168.254.250 to-ports=9100
- add action=dst-nat chain=dstnat dst-port=53,853,5353 in-interface-list=\
- !WAN-LIST protocol=udp src-address-list=!LOCAL_LAN to-addresses=\
- 192.168.254.250 to-ports=853
- add action=dst-nat chain=dstnat comment=----------- dst-address=185.23.83.133 \
- dst-port=14620 protocol=tcp to-addresses=192.168.254.23 to-ports=14620
- add action=dst-nat chain=dstnat comment=adguard dst-address=185.23.83.133 \
- dst-port=9617 protocol=tcp to-addresses=192.168.254.250 to-ports=9617
- add action=dst-nat chain=dstnat comment=bb-exporter dst-address=185.23.83.133 \
- dst-port=9515 protocol=tcp to-addresses=192.168.254.23 to-ports=9115
- add action=dst-nat chain=dstnat comment=adguard disabled=yes dst-address=\
- 185.23.83.133 dst-port=3344 protocol=tcp to-addresses=192.168.254.23 \
- to-ports=443
- add action=dst-nat chain=dstnat comment=DNS-QUIC-S22 dst-address=\
- 185.23.83.133 dst-port=53,853,5353 log-prefix=vps protocol=udp \
- src-address=95.142.47.131 to-addresses=192.168.254.250 to-ports=53
- add action=dst-nat chain=dstnat comment="ZABBIX PC" dst-address=185.23.83.133 \
- dst-port=12350 log-prefix=zabbix-ps protocol=tcp src-address=\
- 95.142.47.131 to-addresses=192.168.254.38 to-ports=10050
- add action=dst-nat chain=dstnat comment=DNS_REDIRECT disabled=yes \
- dst-address=!10.15.12.100 dst-port=53 protocol=udp to-addresses=\
- 192.168.254.250 to-ports=53
- add action=dst-nat chain=dstnat comment=DNS_REDIRECT disabled=yes dst-port=53 \
- protocol=tcp to-addresses=192.168.254.250 to-ports=53
- add action=dst-nat chain=dstnat comment=DNS_REDIRECT disabled=yes dst-port=\
- 853 protocol=udp to-addresses=192.168.254.250 to-ports=853
- add action=dst-nat chain=dstnat comment=DNS_REDIRECT disabled=yes dst-port=\
- 5353 protocol=tcp to-addresses=192.168.254.250 to-ports=5353
- /ip firewall raw
- add action=drop chain=prerouting in-interface=vrn.tv src-address-list=\
- "Honeypot Hacker"
- add action=drop chain=prerouting in-interface=vrn.tv src-address-list=\
- "Hacker Scanners"
- add action=drop chain=prerouting dst-port=137,138,139 in-interface-list=\
- WAN-LIST protocol=udp
- /ip firewall service-port
- set ftp disabled=yes
- /ip route
- add blackhole dst-address=172.16.0.0/12
- add blackhole dst-address=192.168.0.0/16
- add disabled=no distance=1 dst-address=45.90.28.199/32 gateway=vrn.tv \
- pref-src="" routing-table=main scope=30 suppress-hw-offload=no \
- target-scope=10
- add disabled=no distance=1 dst-address=5.61.54.61/32 gateway=vrn.tv pref-src=\
- "" routing-table=main scope=30 suppress-hw-offload=yes target-scope=10
- add comment=Adguard disabled=no distance=1 dst-address=104.20.90.0/23 \
- gateway=vrn.tv pref-src="" routing-table=main scope=30 \
- suppress-hw-offload=no target-scope=10
- add comment=LAN->CCC disabled=no distance=1 dst-address=192.168.1.0/24 \
- gateway=10.10.10.1 pref-src="" routing-table=main scope=30 \
- suppress-hw-offload=no target-scope=10
- add disabled=no distance=1 dst-address=10.10.240.0/30 gateway=\
- wireguard-alpina pref-src="" routing-table=main scope=30 \
- suppress-hw-offload=no target-scope=10
- add comment=LAN->Alpina disabled=no distance=1 dst-address=192.168.240.0/24 \
- gateway=10.10.24.1 pref-src="" routing-table=main scope=30 \
- suppress-hw-offload=no target-scope=10
- add comment=10.0.0.0/8 disabled=no distance=1 dst-address=10.15.12.100/32 \
- gateway=WB pref-src="" routing-table=main scope=30 suppress-hw-offload=no \
- target-scope=10
- add comment=Sber disabled=no distance=1 dst-address=91.206.30.0/24 gateway=\
- vrn.tv pref-src="" routing-table=main scope=30 suppress-hw-offload=no \
- target-scope=10
- add disabled=no distance=20 dst-address=46.19.138.67/32 gateway=wireguard2 \
- routing-table=main scope=40 suppress-hw-offload=no target-scope=30
- add disabled=no distance=20 dst-address=185.88.180.0/23 gateway=wireguard2 \
- routing-table=main scope=40 suppress-hw-offload=no target-scope=30
- add disabled=no distance=1 dst-address=10.15.12.0/24 gateway=WB pref-src="" \
- routing-table=main scope=30 suppress-hw-offload=no target-scope=10
- add disabled=no distance=3 dst-address=185.88.181.0/28 gateway=wireguard2 \
- pref-src="" routing-table=main scope=40 suppress-hw-offload=no \
- target-scope=30
- add comment="==Wildberries site route" disabled=no distance=1 dst-address=\
- 185.138.254.1/32 gateway=vrn.tv pref-src="" routing-table=main scope=30 \
- suppress-hw-offload=no target-scope=10
- add comment="==Wildberries site route" disabled=no distance=1 dst-address=\
- 185.138.252.1/32 gateway=vrn.tv pref-src="" routing-table=main scope=30 \
- suppress-hw-offload=no target-scope=10
- add comment="==Wildberries site route" disabled=no distance=1 dst-address=\
- 185.138.253.1/32 gateway=vrn.tv pref-src="" routing-table=main scope=30 \
- suppress-hw-offload=no target-scope=10
- add disabled=no dst-address=10.10.20.0/24 gateway=WB routing-table=main \
- suppress-hw-offload=no
- add disabled=no dst-address=10.20.0.0/14 gateway=WB routing-table=main \
- suppress-hw-offload=no
- add disabled=no dst-address=10.36.0.0/16 gateway=WB routing-table=main \
- suppress-hw-offload=no
- add disabled=no dst-address=10.37.0.0/16 gateway=WB routing-table=main \
- suppress-hw-offload=no
- add disabled=no dst-address=10.168.0.0/14 gateway=WB routing-table=main \
- suppress-hw-offload=no
- add comment=edge-chat.instagram.com disabled=no distance=20 dst-address=\
- 31.13.81.0/24 gateway=wireguard2 routing-table=main scope=40 \
- suppress-hw-offload=no target-scope=30
- add disabled=no distance=1 dst-address=10.42.224.39/20 gateway=WB pref-src="" \
- routing-table=main scope=30 suppress-hw-offload=no target-scope=10
- add comment=WB-SD disabled=no distance=1 dst-address=10.15.103.0/24 gateway=\
- WB pref-src="" routing-table=main scope=30 suppress-hw-offload=no \
- target-scope=10
- add comment=WB-SD disabled=no distance=1 dst-address=10.15.104.0/24 gateway=\
- WB pref-src="" routing-table=main scope=30 suppress-hw-offload=no \
- target-scope=10
- add disabled=no distance=20 dst-address=184.51.224.0/20 gateway=wireguard2 \
- routing-table=main scope=40 suppress-hw-offload=no target-scope=30
- add comment=WB-SD disabled=no distance=1 dst-address=10.15.102.0/24 gateway=\
- WB pref-src="" routing-table=main scope=30 suppress-hw-offload=no \
- target-scope=10
- add comment=Inst disabled=no distance=20 dst-address=157.240.205.0/24 \
- gateway=wireguard2 routing-table=main scope=40 suppress-hw-offload=no \
- target-scope=30
- add comment=LAN->iLO-CCC disabled=no distance=1 dst-address=192.168.5.0/24 \
- gateway=10.10.10.1 pref-src="" routing-table=main scope=30 \
- suppress-hw-offload=no target-scope=10
- /ip service
- set telnet disabled=yes
- set ftp disabled=yes
- set www disabled=yes
- set ssh port=25
- /routing bgp connection
- add as=64999 disabled=yes hold-time=4m input.filter=any-list_network \
- .ignore-as-path-len=yes keepalive-time=1m local.address=185.23.83.133 \
- .role=ebgp multihop=yes name=antifilter.network remote.address=\
- 51.75.66.20/32 .as=65444 routing-table=main
- add as=64514 disabled=no hold-time=4m input.accept-communities="" \
- .accept-ext-communities="" .accept-large-communities="" .filter=\
- any-list_download .ignore-as-path-len=yes keepalive-time=1m \
- local.address=192.168.254.1 .role=ebgp multihop=yes name=\
- antifilter.download remote.address=45.154.73.71/32 .as=65432 \
- routing-table=main
- /routing filter community-ext-list
- add communities=soo:65432:500 list=my
- /routing filter community-large-list
- add communities=65432:500:0 disabled=no list=set1
- /routing filter community-list
- add communities=65432:500 disabled=no list=test
- add communities=65444:700 disabled=no list=bgp_antifilter.network
- add communities=65432:100,65432:300,65432:500 disabled=no list=\
- bgp_antifilter.download
- /routing filter rule
- add chain=discard disabled=yes rule="reject;"
- add chain=antifilter.network_filter disabled=no rule="set gw *0xc; accept"
- add chain=test disabled=no rule="if ( bgp-communities includes 65444:700) {set\
- \_gw *0xc;accept;} else { reject; }"
- add chain=any-list_network disabled=no rule="if ( bgp-communities any-list bgp\
- _antifilter.network ) {set gw *0xc; accept;}else {reject;}"
- add chain=any-list_download disabled=no rule="if ( bgp-communities any-list bg\
- p_antifilter.download ) {set gw *0xc; accept;} else {reject;}"
- /snmp
- set enabled=yes engine-id-suffix=F34E0F2D4E20 trap-generators=interfaces \
- trap-target=95.142.47.131 trap-version=2
- /system clock
- set time-zone-name=Europe/Moscow
- /system logging
- set 0 action=USBinfo
- add disabled=yes topics=bgp,debug
- add disabled=yes prefix="DNS DEBUG" topics=debug,dns,info
- add disabled=yes topics=ipsec,debug
- add action=USBinfo disabled=yes topics=dhcp,ddns
- /system note
- set show-at-login=no
- /system ntp client
- set enabled=yes
- /system ntp server
- set broadcast=yes enabled=yes manycast=yes multicast=yes
- /system ntp client servers
- add address=0.ru.pool.ntp.org
- /system scheduler
- add name=global-scripts on-event=\
- "/system/script { run global-config; run global-functions; }" policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
- start-time=startup
- add interval=1d name=ScriptInstallUpdate on-event=\
- ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
- start-time=startup
- add interval=1h name=check-routeros-update on-event=\
- "/system/script/run check-routeros-update;" policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
- start-date=2023-01-28 start-time=11:19:15
- add interval=5m name=dhcp-to-dns on-event="/system/script/run dhcp-to-dns;" \
- policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
- start-date=2023-01-28 start-time=11:19:59
- add interval=1d name=WorkUp on-event=WB_Up policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
- start-date=2023-03-24 start-time=09:30:00
- add interval=1d name=WorkDown on-event=WB_Up policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
- start-date=2023-03-24 start-time=20:30:00
- add interval=30s name=dns_monitor on-event="/system/script/run dns;" policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
- start-date=2023-07-01 start-time=14:36:04
- /system script
- add dont-require-permissions=no name=erase-antiblock-updated owner=liet \
- policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
- source="{\r\
- \n:for i from=1 to=700 do={\r\
- \n:put \"remove \$i\"\r\
- \n/ip firewall address-list remove [/ip fi address-list find where (list=a\
- ntiblock-updated and address~\"^\$i\\\\..*\")]\r\
- \n:delay 0.1\r\
- \n}\r\
- \n}"
- add dont-require-permissions=no name=antiblock owner=liet policy=\
- read,write,policy,test source=":do {\r\
- \n\r\
- \n :local retryflag true;\r\
- \n :local maxretry 3;\r\
- \n :local delay 120s;\r\
- \n :local url \"https://antifilter.network/download/ipsmart.lst\";\r\
- \n :local listname \"antiblock\";\r\
- \n\r\
- \n :for retry from=1 to=\$maxretry step=1 do={\r\
- \n\r\
- \n :if (retryflag) do={\r\
- \n\r\
- \n :set \$retryflag false;\r\
- \n :set \$counter 0;\r\
- \n\r\
- \n :if (retry > 1) do={\r\
- \n :delay \$delay;\r\
- \n };\r\
- \n\r\
- \n :do {\r\
- \n /ip firewall address-list remove [find where list=(\$lis\
- tname.\"-updated\")];\r\
- \n } on-error={};\r\
- \n\r\
- \n :do {\r\
- \n /ip firewall address-list add list=(\$listname.\"-update\
- d\") address=antifilter.download comment=\"antifilter.download\";\r\
- \n } on-error={};\r\
- \n\r\
- \n :local filesize ([/tool fetch url=\$url keep-result=no as-va\
- lue]->\"total\");\r\
- \n :local chunksize 64000;\r\
- \n :local start 0;\r\
- \n :local end (\$chunksize - 1);\r\
- \n :local chunks (\$filesize / (\$chunksize / 1024));\r\
- \n :local lastchunk (\$filesize % (\$chunksize / 1024));\r\
- \n\r\
- \n :if (\$lastchunk > 0) do={\r\
- \n :set \$chunks (\$chunks + 1);\r\
- \n };\r\
- \n\r\
- \n :for chunk from=1 to=\$chunks step=1 do={\r\
- \n\r\
- \n :local comparesize ([/tool fetch url=\$url keep-result=n\
- o as-value]->\"total\");\r\
- \n\r\
- \n :if (\$comparesize = \$filesize) do={\r\
- \n :set \$data ([:tool fetch url=\$url http-header-fiel\
- d=\"Range: bytes=\$start-\$end\" output=user as-value]->\"data\");\r\
- \n } else={\r\
- \n :set \$data [:toarray \"\"];\r\
- \n :set \$retryflag true;\r\
- \n };\r\
- \n\r\
- \n :local regexp \"^((25[0-5]|(2[0-4]|[01]\?[0-9]\?)[0-9])\
- \\\\.){3}(25[0-5]|(2[0-4]|[01]\?[0-9]\?)[0-9])(\\\\/(3[0-2]|[0-2]\?[0-9]))\
- {0,1}\\\$\";\r\
- \n\r\
- \n :if (\$start > 0) do={\r\
- \n :set \$data [:pick \$data ([:find \$data \"\\n\"]+1)\
- \_[:len \$data]];\r\
- \n };\r\
- \n \r\
- \n :while ([:len \$data]!=0) do={\r\
- \n :local line [:pick \$data 0 [:find \$data \"\\n\"]];\
- \r\
- \n\r\
- \n :if ( \$line ~ \$regexp ) do={ \r\
- \n :do {\r\
- \n /ip firewall address-list add list=(\$listna\
- me.\"-updated\") address=\$line;\r\
- \n :set \$counter (\$counter + 1);\r\
- \n } on-error={}; \r\
- \n };\r\
- \n\r\
- \n :set \$data [:pick \$data ([:find \$data \"\\n\"]+1)\
- \_[:len \$data]];\r\
- \n\r\
- \n :if ([:len \$data] < 256) do={\r\
- \n :set \$data [:toarray \"\"];\r\
- \n };\r\
- \n };\r\
- \n\r\
- \n :set \$start ((\$start-512) + \$chunksize); \r\
- \n :set \$end ((\$end-512) + \$chunksize); \r\
- \n \r\
- \n };\r\
- \n \r\
- \n };\r\
- \n\r\
- \n };\r\
- \n\r\
- \n :if (\$counter > 0) do={\r\
- \n :do {\r\
- \n /ip firewall address-list remove [find where list=\$listname\
- ];\r\
- \n } on-error={};\r\
- \n\r\
- \n :do {\r\
- \n :foreach address in=[/ip firewall address-list find list=(\$\
- listname.\"-updated\")] do={\r\
- \n :do {\r\
- \n /ip firewall address-list set list=\$listname \$addr\
- ess;\r\
- \n } on-error={};\r\
- \n };\r\
- \n } on-error={};\r\
- \n };\r\
- \n\r\
- \n} on-error={};"
- add dont-require-permissions=no name=erase_antiblock owner=liet policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="{\
- \r\
- \n:for i from=1 to=700 do={\r\
- \n:put \"remove \$i\"\r\
- \n/ip firewall address-list remove [/ip fi address-list find where (list=a\
- ntiblock and address~\"^\$i\\\\..*\")]\r\
- \n:delay 0.1\r\
- \n}\r\
- \n}"
- add dont-require-permissions=no name=global-config owner=global-config \
- policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
- source="#!rsc by RouterOS\
- \n# RouterOS script: global-config\
- \n# Copyright (c) 2013-2024 Christian Hesse <[email protected]>\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md\
- \n#\
- \n# global configuration\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/\
- \n\
- \n# Set this to 'true' to disable news and change notifications.\
- \n:global NoNewsAndChangesNotification false;\
- \n\
- \n# Add extra text (or emojis) in notification tags.\
- \n:global IdentityExtra \"\";\
- \n\
- \n# This is used in DNS scripts ('ipsec-to-dns' and fallback in 'dhcp-to-d\
- ns')\
- \n# and backup scripts for file names.\
- \n:global Domain \"example.com\";\
- \n\
- \n# You can send e-mail notifications. Configure the system's mail setting\
- s\
- \n# (/tool/e-mail), then install the module:\
- \n# \$ScriptInstallUpdate mod/notification-email\
- \n# The to-address needs to be filled; cc-address can be empty, one addres\
- s\
- \n# or a comma separated list of addresses.\
- \n:global EmailGeneralTo \"\";\
- \n:global EmailGeneralCc \"\";\
- \n#:global EmailGeneralTo \"[email protected]\";\
- \n#:global EmailGeneralCc \"[email protected],[email protected]\";\
- \n\
- \n# You can send Telegram notifications. Register a bot\
- \n# and add the token and chat ids here, then install the module:\
- \n# \$ScriptInstallUpdate mod/notification-telegram\
- \n:global TelegramTokenId \"\";\
- \n:global TelegramChatId \"\";\
- \n#:global TelegramTokenId \"123456:ABCDEF-GHI\";\
- \n#:global TelegramChatId \"12345678\";\
- \n# Using telegram-chat you have to define trusted chat ids (not group ids\
- !)\
- \n# or user names. Groups allow to chat with devices simultaneously.\
- \n#:global TelegramChatIdsTrusted {\
- \n# \"12345678\";\
- \n# \"example_user\";\
- \n#};\
- \n:global TelegramChatGroups \"(all)\";\
- \n#:global TelegramChatGroups \"(all|home|office)\";\
- \n\
- \n# You can send Matrix notifications. Configure these settings and\
- \n# install the module:\
- \n# \$ScriptInstallUpdate mod/notification-matrix\
- \n:global MatrixHomeServer \"\";\
- \n:global MatrixAccessToken \"\";\
- \n:global MatrixRoom \"\";\
- \n#:global MatrixHomeServer \"matrix.org\";\
- \n#:global MatrixAccessToken \"123456ABCDEFGHI...\";\
- \n#:global MatrixRoom \"!example:matrix.org\";\
- \n\
- \n# You can send Ntfy notifications. Configure these settings and\
- \n# install the module:\
- \n# \$ScriptInstallUpdate mod/notification-ntfy\
- \n:global NtfyServer \"ntfy.sh\";\
- \n:global NtfyTopic \"\";\
- \n\
- \n# It is possible to override e-mail, Telegram, Matrix and Ntfy setting\
- \n# for every script. This is done in arrays, where 'Override' is appended\
- \n# to the variable name, like this:\
- \n#:global EmailGeneralToOverride {\
- \n# \"check-certificates\"=\"[email protected]\";\
- \n# \"backup-email\"=\"[email protected]\";\
- \n#}\
- \n\
- \n# Toggle this to disable symbols in notifications.\
- \n:global NotificationsWithSymbols true;\
- \n# Toggle this to disable color output in terminal/cli.\
- \n:global TerminalColorOutput true;\
- \n\
- \n# This defines what backups to generate and what password to use.\
- \n:global BackupSendBinary false;\
- \n:global BackupSendExport true;\
- \n:global BackupSendGlobalConfig true;\
- \n:global BackupPassword \"v3ry-s3cr3t\";\
- \n:global BackupRandomDelay 0;\
- \n# These credentials are used to upload backup and config export files.\
- \n# SFTP authentication is tricky, you may have to limit authentication\
- \n# methods for your SSH server.\
- \n:global BackupUploadUrl \"sftp://example.com/backup/\";\
- \n:global BackupUploadUser \"mikrotik\";\
- \n:global BackupUploadPass \"v3ry-s3cr3t\";\
- \n\
- \n# This defines the settings for firewall address-lists (fw-addr-lists).\
- \n:global FwAddrLists {\
- \n# \"allow\"={\
- \n# { url=\"https://eworm.de/ros/fw-addr-lists/allow\";\
- \n# cert=\"E1\"; timeout=1w };\
- \n# };\
- \n \"block\"={\
- \n# { url=\"https://eworm.de/ros/fw-addr-lists/block\";\
- \n# cert=\"E1\" };\
- \n { url=\"https://feodotracker.abuse.ch/downloads/ipblocklist_recommen\
- ded.txt\";\
- \n cert=\"GlobalSign Atlas R3 DV TLS CA 2022 Q3\" };\
- \n { url=\"https://sslbl.abuse.ch/blacklist/sslipblacklist.txt\";\
- \n cert=\"GlobalSign Atlas R3 DV TLS CA 2022 Q3\" };\
- \n { url=\"https://www.dshield.org/block.txt\"; cidr=\"/24\";\
- \n cert=\"R3\" };\
- \n# { url=\"https://www.spamhaus.org/drop/drop.txt\";\
- \n# cert=\"Cloudflare Inc ECC CA-3\" };\
- \n# { url=\"https://www.spamhaus.org/drop/edrop.txt\";\
- \n# cert=\"Cloudflare Inc ECC CA-3\" };\
- \n };\
- \n};\
- \n:global FwAddrListTimeOut 1d;\
- \n\
- \n# This defines what log messages to filter or include by topic or messag\
- e\
- \n# text. Regular expressions are supported. Do *NOT* set an empty string,\
- \n# that will filter or include everything!\
- \n# These are filters, so excluding messages from forwarding.\
- \n:global LogForwardFilter \"(debug|info|packet|raw)\";\
- \n:global LogForwardFilterMessage [];\
- \n#:global LogForwardFilterMessage \"message text\";\
- \n#:global LogForwardFilterMessage \"(message text|another text|...)\";\
- \n# ... and another setting with reverse logic. This includes messages eve\
- n\
- \n# if filtered above.\
- \n:global LogForwardInclude [];\
- \n:global LogForwardIncludeMessage [];\
- \n#:global LogForwardInclude \"account\";\
- \n#:global LogForwardIncludeMessage \"message text\";\
- \n\
- \n# Specify an address to enable auto update to version assumed safe.\
- \n# The configured channel (bugfix, current, release-candidate) is appende\
- d.\
- \n:global SafeUpdateUrl \"\";\
- \n#:global SafeUpdateUrl \"https://example.com/ros/safe-update/\";\
- \n# Allow to install patch updates automatically.\
- \n:global SafeUpdatePatch false;\
- \n# Allow to install updates automatically if seen in neighbor list.\
- \n:global SafeUpdateNeighbor false;\
- \n:global SafeUpdateNeighborIdentity \"\";\
- \n# Install *ALL* updates automatically!\
- \n# Set to all upper-case \"Yes, please!\" to enable.\
- \n:global SafeUpdateAll \"no\";\
- \n\
- \n# These thresholds control when to send health notification\
- \n# on temperature and voltage.\
- \n:global CheckHealthTemperature {\
- \n temperature=50;\
- \n cpu-temperature=70;\
- \n board-temperature1=50;\
- \n board-temperature2=50;\
- \n};\
- \n# This is deviation on recovery threshold against notification flooding.\
- \n:global CheckHealthTemperatureDeviation 3;\
- \n:global CheckHealthVoltageLow 115;\
- \n:global CheckHealthVoltagePercent 10;\
- \n\
- \n# Access-list entries matching this comment are updated\
- \n# with daily pseudo-random PSK.\
- \n:global DailyPskMatchComment \"Daily PSK\";\
- \n:global DailyPskQrCodeUrl \"https://www.eworm.de/cgi-bin/cqrlogo-wifi.cg\
- i\";\
- \n:global DailyPskSecrets {\
- \n { \"Abusive\"; \"Aggressive\"; \"Bored\"; \"Chemical\"; \"Cold\";\
- \n \"Cruel\"; \"Curved\"; \"Delightful\"; \"Discreet\"; \"Elite\";\
- \n \"Evasive\"; \"Faded\"; \"Flat\"; \"Future\"; \"Grandiose\";\
- \n \"Hanging\"; \"Humorous\"; \"Interesting\"; \"Magenta\";\
- \n \"Magnificent\"; \"Numerous\"; \"Optimal\"; \"Pathetic\";\
- \n \"Possessive\"; \"Remarkable\"; \"Rightful\"; \"Ruthless\";\
- \n \"Stale\"; \"Unusual\"; \"Useless\"; \"Various\" };\
- \n { \"Adhesive\"; \"Amusing\"; \"Astonishing\"; \"Frantic\";\
- \n \"Kindhearted\"; \"Limping\"; \"Roasted\"; \"Robust\";\
- \n \"Staking\"; \"Thundering\"; \"Ultra\"; \"Unreal\" };\
- \n { \"Belief\"; \"Button\"; \"Curtain\"; \"Edge\"; \"Jewel\";\
- \n \"String\"; \"Whistle\" }\
- \n};\
- \n\
- \n# Specify how to assemble DNS names in ipsec-to-dns.\
- \n:global HostNameInZone true;\
- \n:global PrefixInZone true;\
- \n\
- \n# Run different commands with multiple mode-button presses.\
- \n:global ModeButton {\
- \n 1=\"/system/script/run leds-toggle-mode;\";\
- \n 2=\":global Identity; :global SendNotification; :global SymbolForNotif\
- ication; \\\$SendNotification ([ \\\$SymbolForNotification \\\"earth\\\" ]\
- \_. \\\"Hello...\\\") (\\\"Hello world, \\\" . \\\$Identity . \\\" calling\
- !\\\");\";\
- \n 3=\"/system/shutdown;\";\
- \n 4=\"/system/reboot;\";\
- \n 5=\":global BridgePortVlan; \\\$BridgePortVlan alt;\";\
- \n# add more here...\
- \n};\
- \n# This led gives visual feedback if type is 'on' or 'off'.\
- \n:global ModeButtonLED \"user-led\";\
- \n\
- \n# Run commands on SMS action.\
- \n:global SmsAction {\
- \n bridge-port-vlan-alt=\":global BridgePortVlan; \\\$BridgePortVlan alt;\
- \";\
- \n reboot=\"/system/reboot;\";\
- \n shutdown=\"/system/shutdown;\";\
- \n# add more here...\
- \n};\
- \n\
- \n# Run commands by hooking into SMS forward.\
- \n:global SmsForwardHooks {\
- \n { match=\"magic string\";\
- \n allowed-number=\"12345678\";\
- \n command=\"/system/script/run ...\" };\
- \n# add more here...\
- \n};\
- \n\
- \n# This is the address used to send gps data to.\
- \n:global GpsTrackUrl \"https://example.com/index.php\";\
- \n\
- \n# This is the base url to fetch scripts from.\
- \n:global ScriptUpdatesBaseUrl \"https://git.eworm.de/cgit/routeros-script\
- s/plain/\";\
- \n# alternative urls - main: stable code - next: currently in development\
- \n#:global ScriptUpdatesBaseUrl \"https://raw.githubusercontent.com/eworm-\
- de/routeros-scripts/main/\";\
- \n#:global ScriptUpdatesBaseUrl \"https://raw.githubusercontent.com/eworm-\
- de/routeros-scripts/next/\";\
- \n#:global ScriptUpdatesBaseUrl \"https://gitlab.com/eworm-de/routeros-scr\
- ipts/raw/main/\";\
- \n#:global ScriptUpdatesBaseUrl \"https://gitlab.com/eworm-de/routeros-scr\
- ipts/raw/next/\";\
- \n:global ScriptUpdatesUrlSuffix \"\";\
- \n# use next branch with default url (git.eworm.de)\
- \n#:global ScriptUpdatesUrlSuffix \"\?h=next\";\
- \n\
- \n# Use this for defaults with \$ScriptRunOnce\
- \n# Install module with:\
- \n# \$ScriptInstallUpdate mod/scriptrunonce\
- \n:global ScriptRunOnceBaseUrl \"\";\
- \n:global ScriptRunOnceUrlSuffix \"\";\
- \n\
- \n# This project is developed in private spare time and usage is free of c\
- harge\
- \n# for you. If you like the scripts and think this is of value for you or\
- \_your\
- \n# business please consider a donation:\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/#donate\
- \n# Enable this to silence donation hint.\
- \n:global IDonate false;\
- \n\
- \n# Use this for certificate auto-renew\
- \n:global CertRenewUrl \"\";\
- \n#:global CertRenewUrl \"https://example.com/certificates/\";\
- \n:global CertRenewTime 3w;\
- \n:global CertRenewPass {\
- \n \"v3ry-s3cr3t\";\
- \n \"4n0th3r-s3cr3t\";\
- \n};\
- \n:global CertWarnTime 2w;\
- \n:global CertIssuedExportPass {\
- \n \"cert1-cn\"=\"v3ry-s3cr3t\";\
- \n \"cert2-cn\"=\"4n0th3r-s3cr3t\";\
- \n};\
- \n\
- \n# load custom settings from overlay\
- \n# Warning: Do *NOT* copy this code to overlay!\
- \n:do {\
- \n /system/script/run global-config-overlay;\
- \n} on-error={\
- \n :log error (\"Loading configuration from overlay failed!\");\
- \n}\
- \n"
- add dont-require-permissions=no name=global-config-overlay owner=liet-phone \
- policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
- source="# Overlay for global configuration by RouterOS Scripts\
- \n# Copyright (c) 2013-2023 Christian Hesse <[email protected]>\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md\
- \n#\
- \n# global configuration, custom overlay\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/\
- \n\
- \n# Copy relevant configuration from global-config, paste and modify it he\
- re.\
- \n:global Domain \"dune.local\";\
- \n:global HostNameInZone true;\
- \n:global PrefixInZone false;\
- \n:global ServerNameInZone false;\
- \n\
- \n\
- \n# End of global-config-overlay\
- \n"
- add dont-require-permissions=no name=global-functions owner=global-functions \
- policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
- source="#!rsc by RouterOS\
- \n# RouterOS script: global-functions\
- \n# Copyright (c) 2013-2024 Christian Hesse <[email protected]>\
- \n# Michael Gisbers <[email protected]>\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md\
- \n#\
- \n# requires RouterOS, version=7.10beta5\
- \n#\
- \n# global functions\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/\
- \n\
- \n:local 0 \"global-functions\";\
- \n\
- \n# expected configuration version\
- \n:global ExpectedConfigVersion 116;\
- \n\
- \n# global variables not to be changed by user\
- \n:global GlobalFunctionsReady false;\
- \n:global FetchUserAgent (\"User-Agent: Mikrotik/\" . [ /system/resource/g\
- et version ] . \" Fetch\");\
- \n:global Identity [ /system/identity/get name ];\
- \n\
- \n# global functions\
- \n:global AlignRight;\
- \n:global CertificateAvailable;\
- \n:global CertificateDownload;\
- \n:global CertificateNameByCN;\
- \n:global CharacterMultiply;\
- \n:global CharacterReplace;\
- \n:global CleanFilePath;\
- \n:global DeviceInfo;\
- \n:global Dos2Unix;\
- \n:global DownloadPackage;\
- \n:global EitherOr;\
- \n:global EscapeForRegEx;\
- \n:global FormatLine;\
- \n:global FormatMultiLines;\
- \n:global GetMacVendor;\
- \n:global GetRandom20CharAlNum;\
- \n:global GetRandom20CharHex;\
- \n:global GetRandomNumber;\
- \n:global Grep;\
- \n:global HexToNum;\
- \n:global HumanReadableNum;\
- \n:global IfThenElse;\
- \n:global IsDefaultRouteReachable;\
- \n:global IsDNSResolving;\
- \n:global IsFullyConnected;\
- \n:global IsMacLocallyAdministered;\
- \n:global IsTimeSync;\
- \n:global LogPrintExit2;\
- \n:global LogPrintOnce;\
- \n:global MAX;\
- \n:global MIN;\
- \n:global MkDir;\
- \n:global NotificationFunctions;\
- \n:global ParseDate;\
- \n:global ParseJson;\
- \n:global ParseKeyValueStore;\
- \n:global PrettyPrint;\
- \n:global RandomDelay;\
- \n:global RequiredRouterOS;\
- \n:global ScriptFromTerminal;\
- \n:global ScriptInstallUpdate;\
- \n:global ScriptLock;\
- \n:global SendNotification;\
- \n:global SendNotification2;\
- \n:global SymbolByUnicodeName;\
- \n:global SymbolForNotification;\
- \n:global Unix2Dos;\
- \n:global UrlEncode;\
- \n:global ValidateSyntax;\
- \n:global VersionToNum;\
- \n:global WaitDefaultRouteReachable;\
- \n:global WaitDNSResolving;\
- \n:global WaitForFile;\
- \n:global WaitFullyConnected;\
- \n:global WaitTimeSync;\
- \n\
- \n# align string to the right\
- \n:global AlignRight do={\
- \n :local Input [ :tostr \$1 ];\
- \n :local Len [ :tonum \$2 ];\
- \n\
- \n :global CharacterMultiply;\
- \n :global EitherOr;\
- \n\
- \n :set Len [ \$EitherOr \$Len 8 ];\
- \n :local Spaces [ \$CharacterMultiply \" \" \$Len ];\
- \n\
- \n :return ([ :pick \$Spaces 0 (\$Len - [ :len \$Input ]) ] . \$Input);\
- \n}\
- \n\
- \n# check and download required certificate\
- \n:set CertificateAvailable do={\
- \n :local CommonName [ :tostr \$1 ];\
- \n\
- \n :global CertificateDownload;\
- \n :global LogPrintExit2;\
- \n :global ParseKeyValueStore;\
- \n\
- \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\
- \n [ /certificate/settings/get crl-download ] = true && \\\
- \n [ /certificate/settings/get crl-store ] = \"system\") do={\
- \n \$LogPrintExit2 warning \$0 (\"This system has low free flash space \
- but \" . \\\
- \n \"is configured to download certificate CRLs to system!\") false;\
- \n }\
- \n\
- \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\
- ) do={\
- \n \$LogPrintExit2 info \$0 (\"Certificate with CommonName \\\"\" . \$C\
- ommonName . \"\\\" not available.\") false;\
- \n :if ([ \$CertificateDownload \$CommonName ] = false) do={\
- \n :return false;\
- \n }\
- \n }\
- \n\
- \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\
- e ] ];\
- \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\
- ertVal->\"skid\")) do={\
- \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\
- \_= 0) do={\
- \n \$LogPrintExit2 info \$0 (\"Certificate chain for \\\"\" . \$Commo\
- nName . \\\
- \n \"\\\" is incomplete, missing \\\"\" . ([ \$ParseKeyValueStore (\
- \$CertVal->\"issuer\") ]->\"CN\") . \"\\\".\") false;\
- \n :if ([ \$CertificateDownload \$CommonName ] = false) do={\
- \n :return false;\
- \n }\
- \n }\
- \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\
- \") ] ];\
- \n }\
- \n :return true;\
- \n}\
- \n\
- \n# download and import certificate\
- \n:set CertificateDownload do={\
- \n :local CommonName [ :tostr \$1 ];\
- \n\
- \n :global FetchUserAgent;\
- \n :global ScriptUpdatesBaseUrl;\
- \n :global ScriptUpdatesUrlSuffix;\
- \n\
- \n :global CertificateNameByCN;\
- \n :global LogPrintExit2;\
- \n :global UrlEncode;\
- \n :global WaitForFile;\
- \n\
- \n \$LogPrintExit2 info \$0 (\"Downloading and importing certificate with\
- \_\" . \\\
- \n \"CommonName \\\"\" . \$CommonName . \"\\\".\") false;\
- \n :do {\
- \n :local LocalFileName (\$CommonName . \".pem\");\
- \n :local UrlFileName ([ \$UrlEncode \$CommonName ] . \".pem\");\
- \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ \
- \$FetchUserAgent }) \\\
- \n (\$ScriptUpdatesBaseUrl . \"certs/\" . \$UrlFileName . \$ScriptUpd\
- atesUrlSuffix) \\\
- \n dst-path=\$LocalFileName as-value;\
- \n \$WaitForFile \$LocalFileName;\
- \n /certificate/import file-name=\$LocalFileName passphrase=\"\" as-val\
- ue;\
- \n :delay 1s;\
- \n /file/remove \$LocalFileName;\
- \n\
- \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$LocalFile\
- Name . \"_[0-9]+\\\$\") ] do={\
- \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\
- \n }\
- \n } on-error={\
- \n \$LogPrintExit2 warning \$0 (\"Failed importing certificate with \" \
- . \\\
- \n \"CommonName \\\"\" . \$CommonName . \"\\\"!\") false;\
- \n :return false;\
- \n }\
- \n :return true;\
- \n}\
- \n\
- \n# name a certificate by its common-name\
- \n:set CertificateNameByCN do={\
- \n :local CommonName [ :tostr \$1 ];\
- \n\
- \n :global CharacterReplace;\
- \n\
- \n :local Cert [ /certificate/find where common-name=\$CommonName ];\
- \n /certificate/set \$Cert \\\
- \n name=[ \$CharacterReplace [ \$CharacterReplace [ \$CharacterReplace \
- \$CommonName \"'\" \"-\" ] \" \" \"-\" ] \"---\" \"-\" ];\
- \n}\
- \n\
- \n# multiply given character(s)\
- \n:set CharacterMultiply do={\
- \n :local Return \"\";\
- \n :for I from=1 to=\$2 do={\
- \n :set Return (\$Return . \$1);\
- \n }\
- \n :return \$Return;\
- \n}\
- \n\
- \n# character replace\
- \n:set CharacterReplace do={\
- \n :local String [ :tostr \$1 ];\
- \n :local ReplaceFrom [ :tostr \$2 ];\
- \n :local ReplaceWith [ :tostr \$3 ];\
- \n :local Return \"\";\
- \n\
- \n :if (\$ReplaceFrom = \"\") do={\
- \n :return \$String;\
- \n }\
- \n\
- \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\
- \n :local Pos [ :find \$String \$ReplaceFrom ];\
- \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\
- \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\
- \_\$String ] ];\
- \n }\
- \n\
- \n :return (\$Return . \$String);\
- \n}\
- \n\
- \n# clean file path\
- \n:set CleanFilePath do={\
- \n :local Path [ :tostr \$1 ];\
- \n\
- \n :global CharacterReplace;\
- \n\
- \n :while (\$Path ~ \"//\") do={\
- \n :set \$Path [ \$CharacterReplace \$Path \"//\" \"/\" ];\
- \n }\
- \n :if ([ :pick \$Path 0 ] = \"/\") do={\
- \n :set Path [ :pick \$Path 1 [ :len \$Path ] ];\
- \n }\
- \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={\
- \n :set Path [ :pick \$Path 0 ([ :len \$Path ] - 1) ];\
- \n }\
- \n\
- \n :return \$Path;\
- \n}\
- \n\
- \n# get readable device info\
- \n:set DeviceInfo do={\
- \n :global ExpectedConfigVersion;\
- \n :global Identity;\
- \n\
- \n :global IfThenElse;\
- \n :global FormatLine;\
- \n\
- \n :local License [ /system/license/get ];\
- \n :local Resource [ /system/resource/get ];\
- \n :local RouterBoard;\
- \n :do {\
- \n :set RouterBoard [[ :parse \"/system/routerboard/get\" ]];\
- \n } on-error={ }\
- \n :local Snmp [ /snmp/get ];\
- \n :local Update [ /system/package/update/get ];\
- \n\
- \n :return ( \\\
- \n [ \$FormatLine \"Hostname\" \$Identity ] . \"\\n\" . \\\
- \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\
- \n ([ \$FormatLine \"Location\" (\$Snmp->\"location\") ] . \"\\n\") ]\
- \_. \\\
- \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\
- \n ([ \$FormatLine \"Contact\" (\$Snmp->\"contact\") ] . \"\\n\") ] .\
- \_\\\
- \n [ \$FormatLine \"Board name\" (\$Resource->\"board-name\") ] . \"\\n\
- \" . \\\
- \n [ \$FormatLine \"Architecture\" (\$Resource->\"architecture-name\") \
- ] . \"\\n\" . \\\
- \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true) \\\
- \n ([ \$FormatLine \"Model\" (\$RouterBoard->\"model\") ] . \\\
- \n [ \$IfThenElse ([ :len (\$RouterBoard->\"revision\") ] > 0) \\\
- \n (\" \" . \$RouterBoard->\"revision\") ] . \"\\n\" . \\\
- \n [ \$FormatLine \"Serial number\" (\$RouterBoard->\"serial-number\
- \") ] . \"\\n\") ] . \\\
- \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\
- \n ([ \$FormatLine \"License\" (\$License->\"level\") ] . \"\\n\") ] \
- . \\\
- \n \"RouterOS:\\n\" . \\\
- \n [ \$FormatLine \" Channel\" (\$Update->\"channel\") ] . \"\\n\" .\
- \_\\\
- \n [ \$FormatLine \" Installed\" (\$Update->\"installed-version\") ]\
- \_. \"\\n\" . \\\
- \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\
- ing\" && \\\
- \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\
- \_\\\
- \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\
- \_. \"\\n\") ] . \\\
- \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\
- \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\
- firmware\") \\\
- \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\
- e\") ] . \"\\n\") ] . \\\
- \n \"RouterOS-Scripts:\\n\" . \\\
- \n [ \$FormatLine \" Version\" \$ExpectedConfigVersion ]);\
- \n}\
- \n\
- \n# convert line endings, DOS -> UNIX\
- \n:set Dos2Unix do={\
- \n :local Input [ :tostr \$1 ];\
- \n\
- \n :global CharacterReplace;\
- \n\
- \n :return [ \$CharacterReplace \$Input (\"\\r\\n\") (\"\\n\") ];\
- \n}\
- \n\
- \n# download package from upgrade server\
- \n:set DownloadPackage do={\
- \n :local PkgName [ :tostr \$1 ];\
- \n :local PkgVer [ :tostr \$2 ];\
- \n :local PkgArch [ :tostr \$3 ];\
- \n :local PkgDir [ :tostr \$4 ];\
- \n\
- \n :global CertificateAvailable;\
- \n :global CleanFilePath;\
- \n :global LogPrintExit2;\
- \n :global MkDir;\
- \n :global WaitForFile;\
- \n\
- \n :if ([ :len \$PkgName ] = 0) do={ :return false; }\
- \n :if ([ :len \$PkgVer ] = 0) do={ :set PkgVer [ /system/package/updat\
- e/get installed-version ]; }\
- \n :if ([ :len \$PkgArch ] = 0) do={ :set PkgArch [ /system/resource/get \
- architecture-name ]; }\
- \n\
- \n :if (\$PkgName = \"system\") do={ :set PkgName \"routeros\"; }\
- \n\
- \n :local PkgFile (\$PkgName . \"-\" . \$PkgVer . \"-\" . \$PkgArch . \".\
- npk\");\
- \n :if (\$PkgArch = \"x86_64\") do={ :set PkgFile (\$PkgName . \"-\" . \$\
- PkgVer . \".npk\"); }\
- \n :local PkgDest [ \$CleanFilePath (\$PkgDir . \"/\" . \$PkgFile) ];\
- \n\
- \n :if ([ \$MkDir \$PkgDir ] = false) do={\
- \n \$LogPrintExit2 warning \$0 (\"Failed creating directory, not downlo\
- ading package.\") false;\
- \n :return false;\
- \n }\
- \n\
- \n :if ([ :len [ /file/find where name=\$PkgDest type=\"package\" ] ] > 0\
- ) do={\
- \n \$LogPrintExit2 info \$0 (\"Package file \" . \$PkgName . \" already\
- \_exists.\") false;\
- \n :return true;\
- \n }\
- \n\
- \n :if ([ \$CertificateAvailable \"R3\" ] = false) do={\
- \n \$LogPrintExit2 error \$0 (\"Downloading required certificate failed\
- .\") true;\
- \n }\
- \n\
- \n :local Url (\"https://upgrade.mikrotik.com/routeros/\" . \$PkgVer . \"\
- /\" . \$PkgFile);\
- \n \$LogPrintExit2 info \$0 (\"Downloading package file '\" . \$PkgName .\
- \_\"'...\") false;\
- \n \$LogPrintExit2 debug \$0 (\"... from url: \" . \$Url) false;\
- \n :local Retry 3;\
- \n :while (\$Retry > 0) do={\
- \n :do {\
- \n /tool/fetch check-certificate=yes-without-crl \$Url dst-path=\$Pkg\
- Dest;\
- \n \$WaitForFile \$PkgDest;\
- \n\
- \n :if ([ /file/get [ find where name=\$PkgDest ] type ] = \"package\
- \") do={\
- \n :return true;\
- \n }\
- \n } on-error={\
- \n \$LogPrintExit2 debug \$0 (\"Downloading package file failed.\") f\
- alse;\
- \n }\
- \n\
- \n /file/remove [ find where name=\$PkgDest ];\
- \n :set Retry (\$Retry - 1);\
- \n }\
- \n\
- \n \$LogPrintExit2 warning \$0 (\"Downloading package file '\" . \$PkgNam\
- e . \"' failed.\") false;\
- \n :return false;\
- \n}\
- \n\
- \n# return either first (if \"true\") or second\
- \n:set EitherOr do={\
- \n :global IfThenElse;\
- \n\
- \n :if ([ :typeof \$1 ] = \"num\") do={\
- \n :return [ \$IfThenElse (\$1 != 0) \$1 \$2 ];\
- \n }\
- \n :if ([ :typeof \$1 ] = \"time\") do={\
- \n :return [ \$IfThenElse (\$1 > 0s) \$1 \$2 ];\
- \n }\
- \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\
- \n}\
- \n\
- \n# escape for regular expression\
- \n:set EscapeForRegEx do={\
- \n :local Input [ :tostr \$1 ];\
- \n\
- \n :if ([ :len \$Input ] = 0) do={\
- \n :return \"\";\
- \n }\
- \n\
- \n :local Return \"\";\
- \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\
- \n\
- \n :for I from=0 to=([ :len \$Input ] - 1) do={\
- \n :local Char [ :pick \$Input \$I ];\
- \n :if ([ :find \$Chars \$Char ]) do={\
- \n :set Char (\"\\\\\" . \$Char);\
- \n }\
- \n :set Return (\$Return . \$Char);\
- \n }\
- \n\
- \n :return \$Return;\
- \n}\
- \n\
- \n# format a line for output\
- \n:set FormatLine do={\
- \n :local Key [ :tostr \$1 ];\
- \n :local Value [ :tostr \$2 ];\
- \n :local Indent [ :tonum \$3 ];\
- \n :local Spaces;\
- \n :local Return \"\";\
- \n\
- \n :global CharacterMultiply;\
- \n :global EitherOr;\
- \n\
- \n :set Indent [ \$EitherOr \$Indent 16 ];\
- \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\
- \n\
- \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\"); }\
- \n :if ([ :len \$Key ] > (\$Indent - 2)) do={\
- \n :set Return (\$Return . \"\\n\" . [ :pick \$Spaces 0 \$Indent ] . \$\
- Value);\
- \n } else={\
- \n :set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \$Retu\
- rn ]) ] . \$Value);\
- \n }\
- \n\
- \n :return \$Return;\
- \n}\
- \n\
- \n# format multiple lines for output\
- \n:set FormatMultiLines do={\
- \n :local Key [ :tostr \$1 ];\
- \n :local Values [ :toarray \$2 ];\
- \n :local Indent [ :tonum \$3 ];\
- \n :local Return;\
- \n\
- \n :global FormatLine;\
- \n\
- \n :set Return [ \$FormatLine \$Key (\$Values->0) \$Indent ];\
- \n :foreach Value in=[ :pick \$Values 1 [ :len \$Values ] ] do={\
- \n :set Return (\$Return . \"\\n\" . [ \$FormatLine \"\" \$Value \$Inde\
- nt ]);\
- \n }\
- \n\
- \n :return \$Return;\
- \n}\
- \n\
- \n# get MAC vendor\
- \n:set GetMacVendor do={\
- \n :local Mac [ :tostr \$1 ];\
- \n\
- \n :global CertificateAvailable;\
- \n :global IsMacLocallyAdministered;\
- \n :global LogPrintExit2;\
- \n\
- \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={\
- \n :return \"locally administered\";\
- \n }\
- \n\
- \n :do {\
- \n :if ([ \$CertificateAvailable \"GTS CA 1P5\" ] = false) do={\
- \n \$LogPrintExit2 warning \$0 (\"Downloading required certificate fa\
- iled.\") true;\
- \n }\
- \n :local Vendor ([ /tool/fetch check-certificate=yes-without-crl \\\
- \n (\"https://api.macvendors.com/\" . [ :pick \$Mac 0 8 ]) output=u\
- ser as-value ]->\"data\");\
- \n :return \$Vendor;\
- \n } on-error={\
- \n :do {\
- \n /tool/fetch check-certificate=yes-without-crl (\"https://api.macve\
- ndors.com/\") \\\
- \n output=none as-value;\
- \n \$LogPrintExit2 debug \$0 (\"The mac vendor is not known in databa\
- se.\") false;\
- \n } on-error={\
- \n \$LogPrintExit2 warning \$0 (\"Failed getting mac vendor.\") false\
- ;\
- \n }\
- \n :return \"unknown vendor\";\
- \n }\
- \n}\
- \n\
- \n# generate random 20 chars alphabetical (A-Z & a-z) and numerical (0-9)\
- \n:set GetRandom20CharAlNum do={\
- \n :global EitherOr;\
- \n\
- \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\
- FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\
- \n}\
- \n\
- \n# generate random 20 chars hex (0-9 and a-f)\
- \n:set GetRandom20CharHex do={\
- \n :global EitherOr;\
- \n\
- \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"01234\
- 56789abcdef\" ];\
- \n}\
- \n\
- \n# generate random number\
- \n:set GetRandomNumber do={\
- \n :global EitherOr;\
- \n\
- \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\
- ;\
- \n}\
- \n\
- \n# return first line that matches a pattern\
- \n:set Grep do={\
- \n :local Input ([ :tostr \$1 ] . \"\\n\");\
- \n :local Pattern [ :tostr \$2 ];\
- \n\
- \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={\
- \n :return [];\
- \n }\
- \n\
- \n :do {\
- \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\
- \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={\
- \n :return \$Line;\
- \n }\
- \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\
- Input ] ];\
- \n } while=([ :len \$Input ] > 0);\
- \n\
- \n :return [];\
- \n}\
- \n\
- \n# convert from hex (string) to num\
- \n:set HexToNum do={\
- \n :local Input [ :tostr \$1 ];\
- \n :local Hex \"0123456789abcdef0123456789ABCDEF\";\
- \n :local Multi 1;\
- \n :local Return 0;\
- \n\
- \n :for I from=([ :len \$Input ] - 1) to=0 do={\
- \n :set Return (\$Return + (([ :find \$Hex [ :pick \$Input \$I ] ] % 16\
- ) * \$Multi));\
- \n :set Multi (\$Multi * 16);\
- \n }\
- \n\
- \n :return \$Return;\
- \n}\
- \n\
- \n# return human readable number\
- \n:global HumanReadableNum do={\
- \n :local Input [ :tonum \$1 ];\
- \n :local Base [ :tonum \$2 ];\
- \n\
- \n :global EitherOr;\
- \n\
- \n :local Prefix \"kMGTPE\";\
- \n :local Pow 1;\
- \n\
- \n :set Base [ \$EitherOr \$Base 1024 ];\
- \n\
- \n :if (\$Input < \$Base) do={\
- \n :return \$Input;\
- \n }\
- \n\
- \n :for I from=0 to=[ :len \$Prefix ] do={\
- \n :set Pow (\$Pow * \$Base);\
- \n :if (\$Input / \$Base < \$Pow) do={\
- \n :set Prefix [ :pick \$Prefix \$I ];\
- \n :local Tmp1 (\$Input * 100 / \$Pow);\
- \n :local Tmp2 (\$Tmp1 / 100);\
- \n :if (\$Tmp2 >= 100) do={\
- \n :return (\$Tmp2 . \$Prefix);\
- \n }\
- \n :return (\$Tmp2 . \".\" . [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \
- \$Tmp1 ] - [ :len \$Tmp2 ] + 1) ] . \$Prefix);\
- \n }\
- \n }\
- \n}\
- \n\
- \n# mimic conditional/ternary operator (condition \? consequent : alternat\
- ive)\
- \n:set IfThenElse do={\
- \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={\
- \n :return \$2;\
- \n }\
- \n :return \$3;\
- \n}\
- \n\
- \n# check if default route is reachable\
- \n:set IsDefaultRouteReachable do={\
- \n :if ([ :len [ /ip/route/find where dst-address=0.0.0.0/0 active routin\
- g-table=main ] ] > 0) do={\
- \n :return true;\
- \n }\
- \n :return false;\
- \n}\
- \n\
- \n# check if DNS is resolving\
- \n:set IsDNSResolving do={\
- \n :global CharacterReplace;\
- \n\
- \n :do {\
- \n :resolve \"low-ttl.eworm.de\";\
- \n } on-error={\
- \n :return false;\
- \n }\
- \n :return true;\
- \n}\
- \n\
- \n# check if system is is fully connected (default route reachable, DNS re\
- solving, time sync)\
- \n:set IsFullyConnected do={\
- \n :global IsDefaultRouteReachable;\
- \n :global IsDNSResolving;\
- \n :global IsTimeSync;\
- \n\
- \n :if ([ \$IsDefaultRouteReachable ] = false) do={\
- \n :return false;\
- \n }\
- \n :if ([ \$IsDNSResolving ] = false) do={\
- \n :return false;\
- \n }\
- \n :if ([ \$IsTimeSync ] = false) do={\
- \n :return false;\
- \n }\
- \n :return true;\
- \n}\
- \n\
- \n# check if mac address is locally administered\
- \n:set IsMacLocallyAdministered do={\
- \n :if ([ :tonum (\"0x\" . [ :pick \$1 0 [ :find \$1 \":\" ] ]) ] & 2 = 2\
- ) do={\
- \n :return true;\
- \n }\
- \n :return false;\
- \n}\
- \n\
- \n# check if system time is sync\
- \n:set IsTimeSync do={\
- \n :global IsTimeSyncCached;\
- \n :global IsTimeSyncResetNtp;\
- \n\
- \n :global LogPrintExit2;\
- \n\
- \n :if (\$IsTimeSyncCached = true) do={\
- \n :return true;\
- \n }\
- \n\
- \n :if ([ /system/ntp/client/get enabled ] = true) do={\
- \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\
- \n :set IsTimeSyncCached true;\
- \n :return true;\
- \n }\
- \n\
- \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\
- \n :set IsTimeSyncResetNtp 0s;\
- \n }\
- \n :local Uptime [ /system/resource/get uptime ];\
- \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={\
- \n :return false;\
- \n }\
- \n\
- \n :set IsTimeSyncResetNtp \$Uptime;\
- \n /system/ntp/client/set enabled=no;\
- \n :delay 20ms;\
- \n /system/ntp/client/set enabled=yes;\
- \n :return false;\
- \n }\
- \n\
- \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\
- \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\
- \n \$LogPrintExit2 debug \$0 (\"No ntp client configured, relying on RT\
- C for CHR free license and x86.\") false;\
- \n :return true;\
- \n }\
- \n\
- \n :if ([ /ip/cloud/get update-time ] = true) do={\
- \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\
- \n :set IsTimeSyncCached true;\
- \n :return true;\
- \n }\
- \n :return false;\
- \n }\
- \n\
- \n \$LogPrintExit2 debug \$0 (\"No time source configured! Returning grac\
- efully...\") false;\
- \n :return true;\
- \n}\
- \n\
- \n# log and print with same text, optionally exit\
- \n:set LogPrintExit2 do={\
- \n :local Severity [ :tostr \$1 ];\
- \n :local Name [ :tostr \$2 ];\
- \n :local Message [ :tostr \$3 ];\
- \n :local Exit [ :tostr \$4 ];\
- \n\
- \n :global PrintDebug;\
- \n :global PrintDebugOverride;\
- \n\
- \n :global EitherOr;\
- \n\
- \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \
- ];\
- \n\
- \n :local PrintSeverity do={\
- \n :global TerminalColorOutput;\
- \n\
- \n :if (\$TerminalColorOutput != true) do={\
- \n :return \$1;\
- \n }\
- \n\
- \n :local Color { debug=96; info=97; warning=93; error=91 };\
- \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\
- \n }\
- \n\
- \n :local Log ([ \$EitherOr \$Name \"<unknown>\" ] . \": \" . \$Message);\
- \n :if (\$Severity ~ (\"^(debug|error|info)\\\$\")) do={\
- \n :if (\$Severity = \"debug\") do={ :log debug \$Log; }\
- \n :if (\$Severity = \"error\") do={ :log error \$Log; }\
- \n :if (\$Severity = \"info\" ) do={ :log info \$Log; }\
- \n } else={\
- \n :log warning \$Log;\
- \n :set Severity \"warning\";\
- \n }\
- \n\
- \n :if (\$Severity != \"debug\" || \$Debug = true) do={\
- \n :put ([ \$PrintSeverity \$Severity ] . \": \" . \$Message);\
- \n }\
- \n\
- \n :if (\$Exit = \"true\") do={\
- \n :error (\"Hard error to exit.\");\
- \n }\
- \n}\
- \n\
- \n# log and print, once until reboot\
- \n:set LogPrintOnce do={\
- \n :local Severity [ :tostr \$1 ];\
- \n :local Name [ :tostr \$2 ];\
- \n :local Message [ :tostr \$3 ];\
- \n\
- \n :global LogPrintExit2;\
- \n\
- \n :global LogPrintOnceMessages;\
- \n\
- \n :if ([ :typeof \$LogPrintOnceMessages ] = \"nothing\") do={\
- \n :set LogPrintOnceMessages ({});\
- \n }\
- \n\
- \n :if (\$LogPrintOnceMessages->\$Message = 1) do={\
- \n :return true;\
- \n }\
- \n\
- \n :set (\$LogPrintOnceMessages->\$Message) 1;\
- \n \$LogPrintExit2 \$Severity \$Name \$Message false;\
- \n}\
- \n\
- \n# get max value\
- \n:set MAX do={\
- \n :if (\$1 > \$2) do={ :return \$1; }\
- \n :return \$2;\
- \n}\
- \n\
- \n# get min value\
- \n:set MIN do={\
- \n :if (\$1 < \$2) do={ :return \$1; }\
- \n :return \$2;\
- \n}\
- \n\
- \n# create directory\
- \n:set MkDir do={\
- \n :local Path [ :tostr \$1 ];\
- \n\
- \n :global CharacterReplace;\
- \n :global CleanFilePath;\
- \n :global GetRandom20CharAlNum;\
- \n :global LogPrintExit2;\
- \n :global WaitForFile;\
- \n\
- \n :local MkTmpfs do={\
- \n :global LogPrintExit2;\
- \n :global WaitForFile;\
- \n\
- \n :if ([ :len [ /disk/find where slot=tmpfs type=tmpfs ] ] = 1) do={\
- \n :return true;\
- \n }\
- \n\
- \n \$LogPrintExit2 info \$0 (\"Creating disk of type tmpfs.\") false;\
- \n /file/remove [ find where name=\"tmpfs\" type=\"directory\" ];\
- \n :do {\
- \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\
- /get total-memory ] / 3);\
- \n \$WaitForFile \"tmpfs\";\
- \n } on-error={\
- \n \$LogPrintExit2 warning \$0 (\"Creating disk of type tmpfs failed!\
- \") false;\
- \n :return false;\
- \n }\
- \n :return true;\
- \n }\
- \n\
- \n :set Path [ \$CleanFilePath \$Path ];\
- \n\
- \n :if (\$Path = \"\") do={\
- \n :return true;\
- \n }\
- \n\
- \n :if ([ :len [ /file/find where name=\$Path type=\"directory\" ] ] = 1)\
- \_do={\
- \n :return true;\
- \n }\
- \n\
- \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\
- \n :if ([ \$MkTmpfs ] = false) do={\
- \n :return false;\
- \n }\
- \n }\
- \n\
- \n :do {\
- \n :local File (\$Path . \"/file\");\
- \n /file/add name=\$File;\
- \n \$WaitForFile \$File;\
- \n /file/remove \$File;\
- \n } on-error={\
- \n \$LogPrintExit2 warning \$0 (\"Making directory '\" . \$Path . \"' f\
- ailed!\") false;\
- \n :return false;\
- \n }\
- \n\
- \n :return true;\
- \n}\
- \n\
- \n# prepare NotificationFunctions array\
- \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={\
- \n :set NotificationFunctions ({});\
- \n}\
- \n\
- \n# parse the date and return a named array\
- \n:set ParseDate do={\
- \n :local Date [ :tostr \$1 ];\
- \n\
- \n :return ({ \"year\"=[ :tonum [ :pick \$Date 0 4 ] ];\
- \n \"month\"=[ :tonum [ :pick \$Date 5 7 ] ];\
- \n \"day\"=[ :tonum [ :pick \$Date 8 10 ] ] });\
- \n}\
- \n\
- \n# parse JSON into array\
- \n# Warning: This is not a complete parser!\
- \n:set ParseJson do={\
- \n :local Input [ :tostr \$1 ];\
- \n\
- \n :local InLen;\
- \n :local Return ({});\
- \n :local Skip 0;\
- \n\
- \n :if ([ :pick \$Input 0 ] = \"{\") do={\
- \n :set Input [ :pick \$Input 1 ([ :len \$Input ] - 1) ];\
- \n }\
- \n :set Input [ :toarray \$Input ];\
- \n :set InLen [ :len \$Input ];\
- \n\
- \n :for I from=0 to=\$InLen do={\
- \n :if (\$Skip > 0 || \$Input->\$I = \"\\n\" || \$Input->\$I = \"\\r\\n\
- \") do={\
- \n :if (\$Skip > 0) do={\
- \n :set \$Skip (\$Skip - 1);\
- \n }\
- \n } else={\
- \n :local Done false;\
- \n :local Key (\$Input->\$I);\
- \n :local Val1 (\$Input->(\$I + 1));\
- \n :local Val2 (\$Input->(\$I + 2));\
- \n :if (\$Val1 = \":\") do={\
- \n :set Skip 2;\
- \n :set (\$Return->\$Key) \$Val2;\
- \n :set Done true;\
- \n }\
- \n :if (\$Done = false && \$Val1 = \":[\") do={\
- \n :local Last false;\
- \n :set Skip 1;\
- \n :set (\$Return->\$Key) ({});\
- \n :do {\
- \n :set Skip (\$Skip + 1);\
- \n :local ValX (\$Input->(\$I + \$Skip));\
- \n :if ([ :pick \$ValX ([ :len \$ValX ] - 1) ] = \"]\") do={\
- \n :set Last true;\
- \n :set ValX [ :pick \$ValX 0 ([ :len \$ValX ] - 1) ];\
- \n }\
- \n :set (\$Return->\$Key) ((\$Return->\$Key), \$ValX);\
- \n } while=(\$Last = false && \$I + \$Skip < \$InLen);\
- \n :set Done true;\
- \n }\
- \n :if (\$Done = false && \$Val1 = \":[]\") do={\
- \n :set Skip 1;\
- \n :set (\$Return->\$Key) ({});\
- \n :set Done true;\
- \n }\
- \n :if (\$Done = false) do={\
- \n :set Skip 1;\
- \n :set (\$Return->\$Key) [ :pick \$Val1 1 [ :len \$Val1 ] ];\
- \n }\
- \n }\
- \n }\
- \n\
- \n :return \$Return;\
- \n}\
- \n\
- \n# parse key value store\
- \n:set ParseKeyValueStore do={\
- \n :local Source \$1;\
- \n :if ([ :typeof \$Source ] != \"array\") do={\
- \n :set Source [ :tostr \$1 ];\
- \n }\
- \n :local Result ({});\
- \n :foreach KeyValue in=[ :toarray \$Source ] do={\
- \n :if ([ :find \$KeyValue \"=\" ]) do={\
- \n :set (\$Result->[ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ])\
- \_\\\
- \n [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [ :len \$Key\
- Value ] ];\
- \n } else={\
- \n :set (\$Result->\$KeyValue) true;\
- \n }\
- \n }\
- \n :return \$Result;\
- \n}\
- \n\
- \n# print lines with trailing carriage return\
- \n:set PrettyPrint do={\
- \n :local Input [ :tostr \$1 ];\
- \n\
- \n :global Unix2Dos;\
- \n\
- \n :put [ \$Unix2Dos \$Input ];\
- \n}\
- \n\
- \n# delay a random amount of seconds\
- \n:set RandomDelay do={\
- \n :global EitherOr;\
- \n :global GetRandomNumber;\
- \n\
- \n :delay ([ \$GetRandomNumber \$1 ] . [ \$EitherOr \$2 \"s\" ]);\
- \n}\
- \n\
- \n# check for required RouterOS version\
- \n:set RequiredRouterOS do={\
- \n :local Caller [ :tostr \$1 ];\
- \n :local Required [ :tostr \$2 ];\
- \n :local Warn [ :tostr \$3 ];\
- \n\
- \n :global IfThenElse;\
- \n :global LogPrintExit2;\
- \n :global VersionToNum;\
- \n\
- \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\
- \\\$\")) do={\
- \n \$LogPrintExit2 error \$0 (\"No valid RouterOS version: \" . \$Requi\
- red) false;\
- \n :return false;\
- \n }\
- \n\
- \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\
- e/update/get installed-version ] ]) do={\
- \n :if (\$Warn = \"true\") do={\
- \n \$LogPrintExit2 warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \
- \$Caller 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\
- \n \" '\" . \$Caller . \"' (at least specific functionality) requir\
- es RouterOS \" . \$Required . \". Please update!\") false;\
- \n }\
- \n :return false;\
- \n }\
- \n :return true;\
- \n}\
- \n\
- \n# check if script is run from terminal\
- \n:set ScriptFromTerminal do={\
- \n :local Script [ :tostr \$1 ];\
- \n\
- \n :global LogPrintExit2;\
- \n\
- \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\
- \n :set Job [ /system/script/job/get \$Job ];\
- \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={\
- \n :set Job [ /system/script/job/get [ find where .id=(\$Job->\"paren\
- t\") ] ];\
- \n }\
- \n :if ((\$Job->\"type\") = \"login\") do={\
- \n \$LogPrintExit2 debug \$0 (\"Script \" . \$Script . \" started fro\
- m terminal.\") false;\
- \n :return true;\
- \n }\
- \n }\
- \n \$LogPrintExit2 debug \$0 (\"Script \" . \$Script . \" NOT started fro\
- m terminal.\") false;\
- \n\
- \n :return false;\
- \n}\
- \n\
- \n# install new scripts, update existing scripts\
- \n:set ScriptInstallUpdate do={\
- \n :local Scripts [ :toarray \$1 ];\
- \n :local NewComment [ :tostr \$2 ];\
- \n\
- \n :global ExpectedConfigVersion;\
- \n :global FetchUserAgent;\
- \n :global Identity;\
- \n :global IDonate;\
- \n :global NoNewsAndChangesNotification;\
- \n :global ScriptUpdatesBaseUrl;\
- \n :global ScriptUpdatesUrlSuffix;\
- \n\
- \n :global CertificateAvailable;\
- \n :global EitherOr;\
- \n :global Grep;\
- \n :global IfThenElse;\
- \n :global LogPrintExit2;\
- \n :global ParseKeyValueStore;\
- \n :global RequiredRouterOS;\
- \n :global SendNotification2;\
- \n :global SymbolForNotification;\
- \n :global ValidateSyntax;\
- \n\
- \n :if ([ \$CertificateAvailable \"E1\" ] = false) do={\
- \n \$LogPrintExit2 warning \$0 (\"Downloading certificate failed, tryin\
- g without.\") false;\
- \n }\
- \n\
- \n :foreach Script in=\$Scripts do={\
- \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\
- \n \$LogPrintExit2 info \$0 (\"Adding new script: \" . \$Script) fals\
- e;\
- \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \
- RouterOS\\n\" comment=\$NewComment;\
- \n }\
- \n }\
- \n\
- \n :local ExpectedConfigVersionBefore \$ExpectedConfigVersion;\
- \n :local ReloadGlobalFunctions false;\
- \n :local ReloadGlobalConfig false;\
- \n\
- \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Rout\
- erOS\\r\?\\n\" ] do={\
- \n :local ScriptVal [ /system/script/get \$Script ];\
- \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \
- ];\
- \n :local SourceNew;\
- \n\
- \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\
- \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\
- \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\
- \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\
- \n \$LogPrintExit2 warning \$0 (\"Policies differ for script '\" . \
- \$ScriptVal->\"name\" . \\\
- \n \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \"'!\")\
- \_false;\
- \n }\
- \n }\
- \n\
- \n :if (!(\$ScriptInfo->\"ignore\" = true)) do={\
- \n :do {\
- \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Scrip\
- tUpdatesBaseUrl ];\
- \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$S\
- criptUpdatesUrlSuffix ];\
- \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\
- Suffix);\
- \n \$LogPrintExit2 debug \$0 (\"Fetching script '\" . \$ScriptVal->\
- \"name\" . \"' from url: \" . \$Url) false;\
- \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\
- \n http-header-field=({ \$FetchUserAgent }) \$Url output=user as-\
- value ];\
- \n :if (\$Result->\"status\" = \"finished\") do={\
- \n :set SourceNew (\$Result->\"data\");\
- \n }\
- \n } on-error={\
- \n :if (\$ScriptVal->\"source\" = \"#!rsc by RouterOS\\n\") do={\
- \n \$LogPrintExit2 warning \$0 (\"Failed fetching script '\" . \$\
- ScriptVal->\"name\" . \\\
- \n \"', removing dummy. Typo on installation\?\") false;\
- \n /system/script/remove \$Script;\
- \n } else={\
- \n \$LogPrintExit2 warning \$0 (\"Failed fetching script '\" . \$\
- ScriptVal->\"name\" . \"'!\") false;\
- \n }\
- \n }\
- \n }\
- \n\
- \n :if ([ :len \$SourceNew ] > 0) do={\
- \n :if (\$SourceNew != \$ScriptVal->\"source\") do={\
- \n :if ([ :pick \$SourceNew 0 18 ] = \"#!rsc by RouterOS\\n\") do={\
- \n :local Required ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\
- \"\\23 requires RouterOS, \") ] ]->\"version\");\
- \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$Required \"0.0\" \
- ] false ] = true) do={\
- \n :if ([ \$ValidateSyntax \$SourceNew ] = true) do={\
- \n \$LogPrintExit2 info \$0 (\"Updating script: \" . \$Script\
- Val->\"name\") false;\
- \n /system/script/set owner=(\$ScriptVal->\"name\") source=\$\
- SourceNew \$Script;\
- \n :if (\$ScriptVal->\"name\" = \"global-config\") do={\
- \n :set ReloadGlobalConfig true;\
- \n }\
- \n :if (\$ScriptVal->\"name\" = \"global-functions\" || \$Scr\
- iptVal->\"name\" ~ (\"^mod/.\")) do={\
- \n :set ReloadGlobalFunctions true;\
- \n }\
- \n } else={\
- \n \$LogPrintExit2 warning \$0 (\"Syntax validation for scrip\
- t '\" . \$ScriptVal->\"name\" . \\\
- \n \"' failed! Ignoring!\") false;\
- \n }\
- \n } else={\
- \n \$LogPrintExit2 warning \$0 (\"The script '\" . \$ScriptVal-\
- >\"name\" . \"' requires RouterOS \" . \\\
- \n \$Required . \", which is not met by your installation. Ig\
- noring!\") false;\
- \n }\
- \n } else={\
- \n \$LogPrintExit2 warning \$0 (\"Looks like new script '\" . \$S\
- criptVal->\"name\" . \\\
- \n \"' is not valid (missing shebang). Ignoring!\") false;\
- \n }\
- \n } else={\
- \n \$LogPrintExit2 debug \$0 (\"Script '\" . \$ScriptVal->\"name\"\
- \_. \"' did not change.\") false;\
- \n }\
- \n } else={\
- \n \$LogPrintExit2 debug \$0 (\"No update for script '\" . \$ScriptVa\
- l->\"name\" . \"'.\") false;\
- \n }\
- \n }\
- \n\
- \n :if (\$ReloadGlobalFunctions = true) do={\
- \n \$LogPrintExit2 info \$0 (\"Reloading global functions.\") false;\
- \n :do {\
- \n /system/script/run global-functions;\
- \n } on-error={\
- \n \$LogPrintExit2 error \$0 (\"Reloading global functions failed!\")\
- \_false;\
- \n }\
- \n }\
- \n\
- \n :if (\$ReloadGlobalConfig = true) do={\
- \n \$LogPrintExit2 info \$0 (\"Reloading global configuration.\") false\
- ;\
- \n :do {\
- \n /system/script/run global-config;\
- \n } on-error={\
- \n \$LogPrintExit2 error \$0 (\"Reloading global configuration failed\
- !\" . \\\
- \n \" Syntax error or missing overlay\?\") false;\
- \n }\
- \n }\
- \n\
- \n :if (\$ExpectedConfigVersionBefore > \$ExpectedConfigVersion) do={\
- \n \$LogPrintExit2 warning \$0 (\"The configuration version decreased f\
- rom \" . \\\
- \n \$ExpectedConfigVersionBefore . \" to \" . \$ExpectedConfigVersion\
- \_. \\\
- \n \". Installed an older version\?\") false;\
- \n }\
- \n\
- \n :if (\$ExpectedConfigVersionBefore < \$ExpectedConfigVersion) do={\
- \n :global GlobalConfigChanges;\
- \n :global GlobalConfigMigration;\
- \n :local ChangeLogCode;\
- \n\
- \n :do {\
- \n :local Url (\$ScriptUpdatesBaseUrl . \"news-and-changes.rsc\" . \$\
- ScriptUpdatesUrlSuffix);\
- \n \$LogPrintExit2 debug \$0 (\"Fetching news, changes and migration:\
- \_\" . \$Url) false;\
- \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\
- \n http-header-field=({ \$FetchUserAgent }) \$Url output=user as-va\
- lue ];\
- \n :if (\$Result->\"status\" = \"finished\") do={\
- \n :set ChangeLogCode (\$Result->\"data\");\
- \n }\
- \n } on-error={\
- \n \$LogPrintExit2 warning \$0 (\"Failed fetching news, changes and m\
- igration!\") false;\
- \n }\
- \n\
- \n :if ([ :len \$ChangeLogCode ] > 0) do={\
- \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\
- \n :do {\
- \n [ :parse \$ChangeLogCode ];\
- \n } on-error={\
- \n \$LogPrintExit2 warning \$0 (\"The changelog failed to run!\")\
- \_false;\
- \n }\
- \n } else={\
- \n \$LogPrintExit2 warning \$0 (\"The changelog failed syntax valid\
- ation!\") false;\
- \n }\
- \n }\
- \n\
- \n :if ([ :len \$GlobalConfigMigration ] > 0) do={\
- \n :for I from=(\$ExpectedConfigVersionBefore + 1) to=\$ExpectedConfi\
- gVersion do={\
- \n :local Migration (\$GlobalConfigMigration->[ :tostr \$I ]);\
- \n :if ([ :typeof \$Migration ] = \"str\") do={\
- \n :if ([ \$ValidateSyntax \$Migration ] = true) do={\
- \n \$LogPrintExit2 info \$0 (\"Applying migration for change \"\
- \_. \$I . \": \" . \$Migration) false;\
- \n :do {\
- \n [ :parse \$Migration ];\
- \n } on-error={\
- \n \$LogPrintExit2 warning \$0 (\"Migration code for change \
- \" . \$I . \" failed to run!\") false;\
- \n }\
- \n } else={\
- \n \$LogPrintExit2 warning \$0 (\"Migration code for change \" \
- . \$I . \" failed syntax validation!\") false;\
- \n }\
- \n }\
- \n }\
- \n }\
- \n\
- \n :local NotificationMessage (\"The configuration version on \" . \$Id\
- entity . \" increased \" . \\\
- \n \"to \" . \$ExpectedConfigVersion . \", current configuration may\
- \_need modification. \" . \\\
- \n \"Please review and update global-config-overlay, then re-run glo\
- bal-config.\");\
- \n \$LogPrintExit2 info \$0 (\$NotificationMessage) false;\
- \n\
- \n :if ([ :len \$GlobalConfigChanges ] > 0) do={\
- \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\
- \");\
- \n :for I from=(\$ExpectedConfigVersionBefore + 1) to=\$ExpectedConfi\
- gVersion do={\
- \n :local Change (\$GlobalConfigChanges->[ :tostr \$I ]);\
- \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\
- \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\
- \n \$LogPrintExit2 info \$0 (\"Change \" . \$I . \": \" . \$Change)\
- \_false;\
- \n }\
- \n } else={\
- \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nNews and\
- \_changes are not available.\");\
- \n }\
- \n\
- \n :if (\$NoNewsAndChangesNotification != true) do={\
- \n :local Link;\
- \n :if (\$IDonate != true) do={\
- \n :set NotificationMessage (\$NotificationMessage . \\\
- \n \"\\n\\n==== donation hint ====\\n\" . \\\
- \n \"This project is developed in private spare time and usage is\
- \_\" . \\\
- \n \"free of charge for you. If you like the scripts and think th\
- is is \" . \\\
- \n \"of value for you or your business please consider a donation\
- .\");\
- \n :set Link \"https://git.eworm.de/cgit/routeros-scripts/about/#do\
- nate\";\
- \n }\
- \n\
- \n \$SendNotification2 ({ origin=\$0; \\\
- \n subject=([ \$SymbolForNotification \"pushpin\" ] . \"News and co\
- nfiguration changes\"); \\\
- \n message=\$NotificationMessage; link=\$Link });\
- \n }\
- \n\
- \n :set GlobalConfigChanges;\
- \n :set GlobalConfigMigration;\
- \n }\
- \n}\
- \n\
- \n# lock script against multiple invocation\
- \n:set ScriptLock do={\
- \n :local Script [ :tostr \$1 ];\
- \n :local DoReturn \$2;\
- \n :local WaitMax ([ :tonum \$3 ] * 10);\
- \n\
- \n :global GetRandom20CharAlNum;\
- \n :global IfThenElse;\
- \n :global LogPrintExit2;\
- \n\
- \n :global ScriptLockOrder;\
- \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\
- \n :set ScriptLockOrder ({});\
- \n }\
- \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\
- \n :set (\$ScriptLockOrder->\$Script) ({});\
- \n }\
- \n\
- \n :local JobCount do={\
- \n :local Script [ :tostr \$1 ];\
- \n\
- \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\
- \n }\
- \n\
- \n :local TicketCount do={\
- \n :local Script [ :tostr \$1 ];\
- \n\
- \n :global ScriptLockOrder;\
- \n\
- \n :local Count 0;\
- \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\
- \n :if ([ :typeof \$Ticket ] != \"nothing\") do={\
- \n :set Count (\$Count + 1);\
- \n }\
- \n }\
- \n :return \$Count;\
- \n }\
- \n\
- \n :local IsFirstTicket do={\
- \n :local Script [ :tostr \$1 ];\
- \n :local Check [ :tostr \$2 ];\
- \n\
- \n :global ScriptLockOrder;\
- \n\
- \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\
- \n :if (\$Ticket = \$Check) do={ :return true; }\
- \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\
- o={ :return false; }\
- \n }\
- \n :return false;\
- \n }\
- \n\
- \n :local AddTicket do={\
- \n :local Script [ :tostr \$1 ];\
- \n :local Add [ :tostr \$2 ];\
- \n\
- \n :global ScriptLockOrder;\
- \n\
- \n :while (true) do={\
- \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\
- \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\
- \n :delay 10ms;\
- \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={ :return tr\
- ue; }\
- \n }\
- \n }\
- \n\
- \n :local RemoveTicket do={\
- \n :local Script [ :tostr \$1 ];\
- \n :local Remove [ :tostr \$2 ];\
- \n\
- \n :global ScriptLockOrder;\
- \n\
- \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\
- \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\
- \n :set (\$ScriptLockOrder->\$Script->\$Id);\
- \n :delay 10ms;\
- \n }\
- \n }\
- \n }\
- \n\
- \n :local CleanupTickets do={\
- \n :local Script [ :tostr \$1 ];\
- \n\
- \n :global ScriptLockOrder;\
- \n\
- \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\
- \n :if ([ :typeof \$Ticket ] != \"nothing\") do={\
- \n :return false;\
- \n }\
- \n }\
- \n\
- \n :set (\$ScriptLockOrder->\$Script) ({});\
- \n }\
- \n\
- \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\
- \n \$LogPrintExit2 error \$0 (\"A script named '\" . \$Script . \"' doe\
- s not exist!\") true;\
- \n }\
- \n\
- \n :if ([ \$JobCount \$Script ] = 0) do={\
- \n \$LogPrintExit2 error \$0 (\"No script '\" . \$Script . \"' is runni\
- ng!\") true;\
- \n }\
- \n\
- \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\
- \n \$LogPrintExit2 error \$0 (\"More tickets than running scripts '\" .\
- \_\$Script . \"', resetting!\") false;\
- \n :set (\$ScriptLockOrder->\$Script) ({});\
- \n /system/script/job/remove [ find where script=\$Script ];\
- \n }\
- \n\
- \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\
- \n \$AddTicket \$Script \$MyTicket;\
- \n\
- \n :local WaitCount 0;\
- \n :while (\$WaitMax > \$WaitCount && ([ \$IsFirstTicket \$Script \$MyTic\
- ket ] = false || [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do\
- ={\
- \n :set WaitCount (\$WaitCount + 1);\
- \n :delay 100ms;\
- \n }\
- \n\
- \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && [ \$TicketCount\
- \_\$Script ] = [ \$JobCount \$Script ]) do={\
- \n \$RemoveTicket \$Script \$MyTicket;\
- \n \$CleanupTickets \$Script;\
- \n :return false;\
- \n }\
- \n\
- \n \$RemoveTicket \$Script \$MyTicket;\
- \n \$LogPrintExit2 info \$0 (\"Script '\" . \$Script . \"' started more t\
- han once\" . [ \$IfThenElse (\$WaitCount > 0) \\\
- \n \" and timed out waiting for lock\" \"\" ] . \"... Aborting.\") [ \$\
- IfThenElse (\$DoReturn = true) false true ];\
- \n :return true;\
- \n}\
- \n\
- \n# send notification via NotificationFunctions - expects at least two str\
- ing arguments\
- \n:set SendNotification do={\
- \n :global SendNotification2;\
- \n\
- \n \$SendNotification2 ({ subject=\$1; message=\$2; link=\$3; silent=\$4 \
- });\
- \n}\
- \n\
- \n# send notification via NotificationFunctions - expects one array argume\
- nt\
- \n:set SendNotification2 do={\
- \n :local Notification \$1;\
- \n\
- \n :global NotificationFunctions;\
- \n\
- \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\
- \n (\$NotificationFunctions->\$FunctionName) \\\
- \n (\"\\\$NotificationFunctions->\\\"\" . \$FunctionName . \"\\\"\") \
- \\\
- \n \$Notification;\
- \n }\
- \n}\
- \n\
- \n# return UTF-8 symbol for unicode name\
- \n:set SymbolByUnicodeName do={\
- \n :local Symbols {\
- \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\
- \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\
- \n \"arrow-down\"=\"\\E2\\AC\\87\";\
- \n \"arrow-up\"=\"\\E2\\AC\\86\";\
- \n \"calendar\"=\"\\F0\\9F\\93\\85\";\
- \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\
- \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\
- \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\
- \n \"cloud\"=\"\\E2\\98\\81\";\
- \n \"cross-mark\"=\"\\E2\\9D\\8C\";\
- \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\
- \n \"fire\"=\"\\F0\\9F\\94\\A5\";\
- \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\
- \n \"heart\"=\"\\E2\\99\\A5\";\
- \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\
- \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\
- \n \"information\"=\"\\E2\\84\\B9\";\
- \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\
- \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\
- \n \"link\"=\"\\F0\\9F\\94\\97\";\
- \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\
- \n \"memo\"=\"\\F0\\9F\\93\\9D\";\
- \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\
- \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\
- \n \"scissors\"=\"\\E2\\9C\\82\";\
- \n \"sparkles\"=\"\\E2\\9C\\A8\";\
- \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\
- \n \"star\"=\"\\E2\\AD\\90\";\
- \n \"warning-sign\"=\"\\E2\\9A\\A0\";\
- \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\
- \n }\
- \n\
- \n :return ((\$Symbols->\$1) . \"\\EF\\B8\\8F\");\
- \n}\
- \n\
- \n# return symbol for notification\
- \n:set SymbolForNotification do={\
- \n :global NotificationsWithSymbols;\
- \n :global SymbolByUnicodeName;\
- \n :global IfThenElse;\
- \n\
- \n :if (\$NotificationsWithSymbols != true) do={\
- \n :return [ \$IfThenElse ([ :len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \
- \"\" ];\
- \n }\
- \n :local Return \"\";\
- \n :foreach Symbol in=[ :toarray \$1 ] do={\
- \n :set Return (\$Return . [ \$SymbolByUnicodeName \$Symbol ]);\
- \n }\
- \n :return (\$Return . \" \");\
- \n}\
- \n\
- \n# convert line endings, UNIX -> DOS\
- \n:set Unix2Dos do={\
- \n :local Input [ :tostr \$1 ];\
- \n\
- \n :global CharacterReplace;\
- \n\
- \n :return [ \$CharacterReplace [ \$CharacterReplace \$Input \\\
- \n (\"\\n\") (\"\\r\\n\") ] (\"\\r\\r\\n\") (\"\\r\\n\") ];\
- \n}\
- \n\
- \n# url encoding\
- \n:set UrlEncode do={\
- \n :local Input [ :tostr \$1 ];\
- \n\
- \n :if ([ :len \$Input ] = 0) do={\
- \n :return \"\";\
- \n }\
- \n\
- \n :local Return \"\";\
- \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\
- \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\
- %24\"; \"%25\"; \"%26\"; \"%27\";\
- \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \
- \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\
- \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \
- \"%7C\"; \"%7D\"; \"%7E\" };\
- \n\
- \n :for I from=0 to=([ :len \$Input ] - 1) do={\
- \n :local Char [ :pick \$Input \$I ];\
- \n :local Replace [ :find \$Chars \$Char ];\
- \n\
- \n :if ([ :typeof \$Replace ] = \"num\") do={\
- \n :set Char (\$Subs->\$Replace);\
- \n }\
- \n :set Return (\$Return . \$Char);\
- \n }\
- \n\
- \n :return \$Return;\
- \n}\
- \n\
- \n# basic syntax validation\
- \n:set ValidateSyntax do={\
- \n :local Code [ :tostr \$1 ];\
- \n\
- \n :do {\
- \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\
- \n } on-error={\
- \n :return false;\
- \n }\
- \n :return true;\
- \n}\
- \n\
- \n# convert version string to numeric value\
- \n:set VersionToNum do={\
- \n :local Input [ :tostr \$1 ];\
- \n :local Multi 0x1000000;\
- \n :local Return 0;\
- \n\
- \n :global CharacterReplace;\
- \n\
- \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\
- \n :foreach I in={ \"alpha\"; \"beta\"; \"rc\" } do={\
- \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\
- \n }\
- \n\
- \n :foreach Value in=([ :toarray \$Input ], 0) do={\
- \n :local Num [ :tonum \$Value ];\
- \n :if (\$Multi = 0x100) do={\
- \n :if ([ :typeof \$Num ] = \"num\") do={\
- \n :set Return (\$Return + 0xff00);\
- \n :set Multi (\$Multi / 0x100);\
- \n } else={\
- \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \
- }\
- \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\
- \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\
- \n }\
- \n }\
- \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\
- lue * \$Multi)); }\
- \n :set Multi (\$Multi / 0x100);\
- \n }\
- \n\
- \n :return \$Return;\
- \n}\
- \n\
- \n# wait for default route to be reachable\
- \n:set WaitDefaultRouteReachable do={\
- \n :global IsDefaultRouteReachable;\
- \n\
- \n :while ([ \$IsDefaultRouteReachable ] = false) do={\
- \n :delay 1s;\
- \n }\
- \n}\
- \n\
- \n# wait for DNS to resolve\
- \n:set WaitDNSResolving do={\
- \n :global IsDNSResolving;\
- \n\
- \n :while ([ \$IsDNSResolving ] = false) do={\
- \n :delay 1s;\
- \n }\
- \n}\
- \n\
- \n# wait for file to be available\
- \n:set WaitForFile do={\
- \n :local FileName [ :tostr \$1 ];\
- \n :local WaitTime [ :totime \$2 ];\
- \n\
- \n :global CleanFilePath;\
- \n :global EitherOr;\
- \n\
- \n :set FileName [ \$CleanFilePath \$FileName ];\
- \n :local I 1;\
- \n :local Delay ([ :totime [ \$EitherOr \$WaitTime 2s ] ] / 20);\
- \n\
- \n :while ([ :len [ /file/find where name=\$FileName ] ] = 0) do={\
- \n :if (\$I >= 20) do={\
- \n :return false;\
- \n }\
- \n :delay \$Delay;\
- \n :set I (\$I + 1);\
- \n }\
- \n :return true;\
- \n}\
- \n\
- \n# wait to be fully connected (default route is reachable, time is sync, \
- DNS resolves)\
- \n:set WaitFullyConnected do={\
- \n :global WaitDefaultRouteReachable;\
- \n :global WaitDNSResolving;\
- \n :global WaitTimeSync;\
- \n\
- \n \$WaitDefaultRouteReachable;\
- \n \$WaitTimeSync;\
- \n \$WaitDNSResolving;\
- \n}\
- \n\
- \n# wait for time to become synced\
- \n:set WaitTimeSync do={\
- \n :global IsTimeSync;\
- \n\
- \n :while ([ \$IsTimeSync ] = false) do={\
- \n :delay 1s;\
- \n }\
- \n}\
- \n\
- \n# load modules\
- \n:foreach Script in=[ /system/script/find where name ~ \"^mod/.\" ] do={\
- \n :local ScriptVal [ /system/script/get \$Script ];\
- \n :if ([ \$ValidateSyntax (\$ScriptVal->\"source\") ] = true) do={\
- \n :do {\
- \n /system/script/run \$Script;\
- \n } on-error={\
- \n \$LogPrintExit2 error \$0 (\"Module '\" . \$ScriptVal->\"name\" . \
- \"' failed to run.\") false;\
- \n }\
- \n } else={\
- \n \$LogPrintExit2 error \$0 (\"Module '\" . \$ScriptVal->\"name\" . \"\
- ' failed syntax validation, skipping.\") false;\
- \n }\
- \n}\
- \n\
- \n# signal we are ready\
- \n:set GlobalFunctionsReady true;\
- \n"
- add dont-require-permissions=no name=check-certificates owner=\
- check-certificates policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\
- !rsc by RouterOS\
- \n# RouterOS script: check-certificates\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md\
- \n#\
- \n# check for certificate validity\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/doc/check-certificate\
- s.md\
- \n\
- \n:local 0 \"check-certificates\";\
- \n:global GlobalFunctionsReady;\
- \n:while (\$GlobalFunctionsReady != true) do={ :delay 500ms; }\
- \n\
- \n:global CertRenewTime;\
- \n:global CertRenewUrl;\
- \n:global CertWarnTime;\
- \n:global Identity;\
- \n\
- \n:global CertificateAvailable\
- \n:global EscapeForRegEx;\
- \n:global IfThenElse;\
- \n:global LogPrintExit2;\
- \n:global ParseKeyValueStore;\
- \n:global ScriptLock;\
- \n:global SendNotification2;\
- \n:global SymbolForNotification;\
- \n:global UrlEncode;\
- \n:global WaitFullyConnected;\
- \n\
- \n:local CheckCertificatesDownloadImport do={\
- \n :local Name [ :tostr \$1 ];\
- \n\
- \n :global CertRenewUrl;\
- \n :global CertRenewPass;\
- \n\
- \n :global CertificateNameByCN;\
- \n :global EscapeForRegEx;\
- \n :global LogPrintExit2;\
- \n :global UrlEncode;\
- \n :global WaitForFile;\
- \n\
- \n :local Return false;\
- \n\
- \n :foreach Type in={ \".pem\"; \".p12\" } do={\
- \n :local CertFileName ([ \$UrlEncode \$Name ] . \$Type);\
- \n :do {\
- \n /tool/fetch check-certificate=yes-without-crl \\\
- \n (\$CertRenewUrl . \$CertFileName) dst-path=\$CertFileName as-v\
- alue;\
- \n \$WaitForFile \$CertFileName;\
- \n\
- \n :local DecryptionFailed true;\
- \n :foreach PassPhrase in=\$CertRenewPass do={\
- \n :local Result [ /certificate/import file-name=\$CertFileName pas\
- sphrase=\$PassPhrase as-value ];\
- \n :if (\$Result->\"decryption-failures\" = 0) do={\
- \n :set DecryptionFailed false;\
- \n }\
- \n }\
- \n /file/remove [ find where name=\$CertFileName ];\
- \n\
- \n :if (\$DecryptionFailed = true) do={\
- \n \$LogPrintExit2 warning \$0 (\"Decryption failed for certificate\
- \_file \" . \$CertFileName) false;\
- \n }\
- \n\
- \n :foreach CertInChain in=[ /certificate/find where name~(\"^\" . [ \
- \$EscapeForRegEx \$CertFileName ] . \"_[0-9]+\\\$\") \\\
- \n common-name!=\$Name !(subject-alt-name~(\"(^|\\\\W)(DNS|IP):\"\
- \_. [ \$EscapeForRegEx \$Name ] . \"(\\\\W|\\\$)\")) !(common-name=[]) ] d\
- o={\
- \n \$CertificateNameByCN [ /certificate/get \$CertInChain common-na\
- me ];\
- \n }\
- \n\
- \n :set Return true;\
- \n } on-error={\
- \n \$LogPrintExit2 debug \$0 (\"Could not download certificate file \
- \" . \$CertFileName) false;\
- \n }\
- \n }\
- \n\
- \n :return \$Return;\
- \n}\
- \n\
- \n:local FormatInfo do={\
- \n :local Cert \$1;\
- \n\
- \n :global FormatLine;\
- \n :global FormatMultiLines;\
- \n :global IfThenElse;\
- \n\
- \n :local FormatExpire do={\
- \n :global CharacterReplace;\
- \n :return [ \$CharacterReplace [ \$CharacterReplace [ :tostr \$1 ] \"w\
- \" \"w \" ] \"d\" \"d \" ];\
- \n }\
- \n\
- \n :local FormatCertChain do={\
- \n :local Cert \$1;\
- \n\
- \n :global EitherOr;\
- \n :global ParseKeyValueStore;\
- \n\
- \n :local CertVal [ /certificate/get \$Cert ];\
- \n :local Return \"\";\
- \n\
- \n :for I from=0 to=5 do={\
- \n :set Return (\$Return . [ \$EitherOr ([ \$ParseKeyValueStore (\$Ce\
- rtVal->\"issuer\") ]->\"CN\") \\\
- \n ([ \$ParseKeyValueStore ((\$CertVal->\"issuer\")->0) ]->\"CN\") \
- ]);\
- \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"ak\
- id\") ] ];\
- \n :if ((\$CertVal->\"akid\") = \"\" || (\$CertVal->\"akid\") = (\$Ce\
- rtVal->\"skid\")) do={\
- \n :return \$Return;\
- \n }\
- \n :set Return (\$Return . \" -> \");\
- \n }\
- \n :return (\$Return . \"...\");\
- \n }\
- \n\
- \n :local CertVal [ /certificate/get \$Cert ];\
- \n\
- \n :return ( \\\
- \n [ \$FormatLine \"Name\" (\$CertVal->\"name\") ] . \"\\n\" . \\\
- \n [ \$IfThenElse ([ :len (\$CertVal->\"common-name\") ] > 0) ([ \$Form\
- atLine \"CommonName\" (\$CertVal->\"common-name\") ] . \"\\n\") ] . \\\
- \n [ \$IfThenElse ([ :len (\$CertVal->\"subject-alt-name\") ] > 0) ([ \
- \$FormatMultiLines \"SubjectAltNames\" (\$CertVal->\"subject-alt-name\") ]\
- \_. \"\\n\") ] . \\\
- \n [ \$FormatLine \"Private key\" [ \$IfThenElse ((\$CertVal->\"private\
- -key\") = true) \"available\" \"missing\" ] ] . \"\\n\" . \\\
- \n [ \$FormatLine \"Fingerprint\" (\$CertVal->\"fingerprint\") ] . \"\\\
- n\" . \\\
- \n [ \$IfThenElse ([ :len (\$CertVal->\"ca\") ] > 0) [ \$FormatLine \"I\
- ssuer\" (\$CertVal->\"ca\") ] [ \$FormatLine \"Issuer chain\" [ \$FormatCe\
- rtChain \$Cert ] ] ] . \"\\n\" . \\\
- \n \"Validity:\\n\" . \\\
- \n [ \$FormatLine \" from\" (\$CertVal->\"invalid-before\") ] . \"\\\
- n\" . \\\
- \n [ \$FormatLine \" to\" (\$CertVal->\"invalid-after\") ] . \"\\n\"\
- \_. \\\
- \n [ \$FormatLine \"Expires in\" [ \$IfThenElse ((\$CertVal->\"expired\
- \") = true) \"expired\" [ \$FormatExpire (\$CertVal->\"expires-after\") ] \
- ] ]);\
- \n}\
- \n\
- \n\$ScriptLock \$0;\
- \n\$WaitFullyConnected;\
- \n\
- \n:foreach Cert in=[ /certificate/find where !revoked !ca !scep-url expire\
- s-after<\$CertRenewTime ] do={\
- \n :local CertVal [ /certificate/get \$Cert ];\
- \n :local CertNew;\
- \n :local LastName;\
- \n\
- \n :do {\
- \n :if ([ :len \$CertRenewUrl ] = 0) do={\
- \n \$LogPrintExit2 info \$0 (\"No CertRenewUrl given.\") true;\
- \n }\
- \n \$LogPrintExit2 info \$0 (\"Attempting to renew certificate \" . (\$\
- CertVal->\"name\") . \".\") false;\
- \n\
- \n :local ImportSuccess false;\
- \n :set LastName (\$CertVal->\"common-name\");\
- \n :set ImportSuccess [ \$CheckCertificatesDownloadImport \$LastName ];\
- \n :foreach SAN in=(\$CertVal->\"subject-alt-name\") do={\
- \n :if (\$ImportSuccess = false) do={\
- \n :set LastName [ :pick \$SAN ([ :find \$SAN \":\" ] + 1) [ :len \
- \$SAN ] ];\
- \n :set ImportSuccess [ \$CheckCertificatesDownloadImport \$LastNam\
- e ];\
- \n }\
- \n }\
- \n\
- \n :if ([ :len (\$CertVal->\"fingerprint\") ] > 0 && \$CertVal->\"finge\
- rprint\" != [ /certificate/get \$Cert fingerprint ]) do={\
- \n \$LogPrintExit2 debug \$0 (\"Certificate '\" . \$CertVal->\"name\"\
- \_. \"' was updated in place.\") false;\
- \n :set CertVal [ /certificate/get \$Cert ];\
- \n } else={\
- \n \$LogPrintExit2 debug \$0 (\"Certificate '\" . \$CertVal->\"name\"\
- \_. \"' was not updated, but replaced.\") false;\
- \n\
- \n :set CertNew [ /certificate/find where name~(\"^\" . [ \$EscapeFor\
- RegEx [ \$UrlEncode \$LastName ] ] . \"\\\\.(p12|pem)_[0-9]+\\\$\") \\\
- \n (common-name=(\$CertVal->\"common-name\") or subject-alt-name~(\
- \"(^|\\\\W)(DNS|IP):\" . [ \$EscapeForRegEx \$LastName ] . \"(\\\\W|\\\$)\
- \")) \\\
- \n fingerprint!=[ :tostr (\$CertVal->\"fingerprint\") ] expires-aft\
- er>\$CertRenewTime ];\
- \n :local CertNewVal [ /certificate/get \$CertNew ];\
- \n\
- \n :if ([ \$CertificateAvailable ([ \$ParseKeyValueStore (\$CertNewVa\
- l->\"issuer\") ]->\"CN\") ] = false) do={\
- \n \$LogPrintExit2 warning \$0 (\"The certificate chain is not avai\
- lable!\") false;\
- \n }\
- \n\
- \n :if ((\$CertVal->\"private-key\") = true && (\$CertVal->\"private-\
- key\") != (\$CertNewVal->\"private-key\")) do={\
- \n /certificate/remove \$CertNew;\
- \n \$LogPrintExit2 warning \$0 (\"Old certificate '\" . (\$CertVal-\
- >\"name\") . \"' has a private key, new certificate does not. Aborting ren\
- ew.\") true;\
- \n }\
- \n\
- \n /ip/service/set certificate=(\$CertNewVal->\"name\") [ find where \
- certificate=(\$CertVal->\"name\") ];\
- \n\
- \n /ip/ipsec/identity/set certificate=(\$CertNewVal->\"name\") [ find\
- \_where certificate=(\$CertVal->\"name\") ];\
- \n /ip/ipsec/identity/set remote-certificate=(\$CertNewVal->\"name\")\
- \_[ find where remote-certificate=(\$CertVal->\"name\") ];\
- \n\
- \n /ip/hotspot/profile/set ssl-certificate=(\$CertNewVal->\"name\") [\
- \_find where ssl-certificate=(\$CertVal->\"name\") ];\
- \n\
- \n /certificate/remove \$Cert;\
- \n /certificate/set \$CertNew name=(\$CertVal->\"name\");\
- \n :set CertNewVal;\
- \n :set CertVal [ /certificate/get \$CertNew ];\
- \n }\
- \n\
- \n \$SendNotification2 ({ origin=\$0; silent=true; \\\
- \n subject=([ \$SymbolForNotification \"lock-with-ink-pen\" ] . \"Cer\
- tificate renewed: \" . (\$CertVal->\"name\")); \\\
- \n message=(\"A certificate on \" . \$Identity . \" has been renewed.\
- \\n\\n\" . [ \$FormatInfo \$CertNew ]) });\
- \n \$LogPrintExit2 info \$0 (\"The certificate \" . (\$CertVal->\"name\
- \") . \" has been renewed.\") false;\
- \n } on-error={\
- \n \$LogPrintExit2 debug \$0 (\"Could not renew certificate \" . (\$Cer\
- tVal->\"name\") . \".\") false;\
- \n }\
- \n}\
- \n\
- \n:foreach Cert in=[ /certificate/find where !revoked !scep-url !(expires-\
- after=[]) \\\
- \n expires-after<\$CertWarnTime !(fingerprint=[]) ] do={\
- \n :local CertVal [ /certificate/get \$Cert ];\
- \n\
- \n :if ([ :len [ /certificate/scep-server/find where ca-cert=(\$CertVal->\
- \"ca\") ] ] > 0) do={\
- \n \$LogPrintExit2 debug \$0 (\"Certificate \\\"\" . (\$CertVal->\"name\
- \") . \"\\\" is handled by SCEP, skipping.\") false;\
- \n } else={\
- \n :local State [ \$IfThenElse ((\$CertVal->\"expired\") = true) \"expi\
- red\" \"is about to expire\" ];\
- \n\
- \n \$SendNotification2 ({ origin=\$0; \\\
- \n subject=([ \$SymbolForNotification \"warning-sign\" ] . \"Certific\
- ate warning: \" . (\$CertVal->\"name\")); \\\
- \n message=(\"A certificate on \" . \$Identity . \" \" . \$State . \"\
- .\\n\\n\" . [ \$FormatInfo \$Cert ]) });\
- \n \$LogPrintExit2 info \$0 (\"The certificate \" . (\$CertVal->\"name\
- \") . \" \" . \$State . \\\
- \n \", it is invalid after \" . (\$CertVal->\"invalid-after\") . \"\
- .\") false;\
- \n }\
- \n}\
- \n"
- add dont-require-permissions=no name=check-routeros-update owner=\
- check-routeros-update policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\
- !rsc by RouterOS\
- \n# RouterOS script: check-routeros-update\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md\
- \n#\
- \n# check for RouterOS update, send notification and/or install\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/doc/check-routeros-up\
- date.md\
- \n\
- \n:local 0 \"check-routeros-update\";\
- \n:global GlobalFunctionsReady;\
- \n:while (\$GlobalFunctionsReady != true) do={ :delay 500ms; }\
- \n\
- \n:global Identity;\
- \n:global SafeUpdateAll;\
- \n:global SafeUpdateNeighbor;\
- \n:global SafeUpdateNeighborIdentity;\
- \n:global SafeUpdatePatch;\
- \n:global SafeUpdateUrl;\
- \n:global SentRouterosUpdateNotification;\
- \n\
- \n:global DeviceInfo;\
- \n:global EscapeForRegEx;\
- \n:global LogPrintExit2;\
- \n:global ScriptFromTerminal;\
- \n:global ScriptLock;\
- \n:global SendNotification2;\
- \n:global SymbolForNotification;\
- \n:global VersionToNum;\
- \n:global WaitFullyConnected;\
- \n\
- \n:local DoUpdate do={\
- \n :if ([ :len [ /system/script/find where name=\"packages-update\" ] ] >\
- \_0) do={\
- \n /system/script/run packages-update;\
- \n } else={\
- \n /system/package/update/install without-paging;\
- \n }\
- \n :error \"Waiting for system to reboot.\";\
- \n}\
- \n\
- \n\$ScriptLock \$0;\
- \n\
- \n\$WaitFullyConnected;\
- \n\
- \n:if ([ :len [ /system/scheduler/find where name=\"_RebootForUpdate\" ] ]\
- \_> 0) do={\
- \n :error \"A reboot for update is already scheduled.\";\
- \n}\
- \n\
- \n\$LogPrintExit2 debug \$0 (\"Checking for updates...\") false;\
- \n/system/package/update/check-for-updates without-paging as-value;\
- \n:local Update [ /system/package/update/get ];\
- \n\
- \n:if ([ \$ScriptFromTerminal \$0 ] = true && (\$Update->\"installed-versi\
- on\") = (\$Update->\"latest-version\")) do={\
- \n \$LogPrintExit2 info \$0 (\"System is already up to date.\") true;\
- \n}\
- \n\
- \n:local NumInstalled [ \$VersionToNum (\$Update->\"installed-version\") ]\
- ;\
- \n:local NumLatest [ \$VersionToNum (\$Update->\"latest-version\") ];\
- \n:local Link (\"https://mikrotik.com/download/changelogs/\" . \$Update->\
- \"channel\" . \"-release-tree\");\
- \n\
- \n:if (\$NumLatest < 117505792) do={\
- \n \$LogPrintExit2 info \$0 (\"The version '\" . (\$Update->\"latest-vers\
- ion\") . \"' is not a valid version.\") true;\
- \n}\
- \n\
- \n:if (\$NumInstalled < \$NumLatest) do={\
- \n :if (\$SafeUpdateAll ~ \"^YES,\? \?PLEASE!\?\\\$\") do={\
- \n \$LogPrintExit2 info \$0 (\"Installing ALL versions automatically, i\
- ncluding \" . \\\
- \n \$Update->\"latest-version\" . \"...\") false;\
- \n \$SendNotification2 ({ origin=\$0; \\\
- \n subject=([ \$SymbolForNotification \"sparkles\" ] . \"RouterOS upd\
- ate: \" . \$Update->\"latest-version\"); \\\
- \n message=(\"Installing ALL versions automatically, including \" . \
- \$Update->\"latest-version\" . \\\
- \n \"... Updating on \" . \$Identity . \"...\"); link=\$Link; silen\
- t=true });\
- \n \$DoUpdate;\
- \n }\
- \n\
- \n :if (\$SafeUpdatePatch = true && (\$NumInstalled & 0xffff0000) = (\$Nu\
- mLatest & 0xffff0000)) do={\
- \n \$LogPrintExit2 info \$0 (\"Version \" . \$Update->\"latest-version\
- \" . \" is a patch release, updating...\") false;\
- \n \$SendNotification2 ({ origin=\$0; \\\
- \n subject=([ \$SymbolForNotification \"sparkles\" ] . \"RouterOS upd\
- ate: \" . \$Update->\"latest-version\"); \\\
- \n message=(\"Version \" . \$Update->\"latest-version\" . \" is a pat\
- ch update for \" . \$Update->\"channel\" . \\\
- \n \", updating on \" . \$Identity . \"...\"); link=\$Link; silent=\
- true });\
- \n \$DoUpdate;\
- \n }\
- \n\
- \n :if (\$SafeUpdateNeighbor = true) do={\
- \n :local Neighbors [ /ip/neighbor/find where platform=\"MikroTik\" ide\
- ntity~\$SafeUpdateNeighborIdentity \\\
- \n version~(\"^\" . [ \$EscapeForRegEx (\$Update->\"latest-version\"\
- ) ] . \"\\\\b\") ];\
- \n :if ([ :len \$Neighbors ] > 0) do={\
- \n :local Neighbor [ /ip/neighbor/get (\$Neighbors->0) identity ];\
- \n \$LogPrintExit2 info \$0 (\"Seen a neighbor (\" . \$Neighbor . \")\
- \_running version \" . \\\
- \n \$Update->\"latest-version\" . \" from \" . \$Update->\"channel\
- \" . \", updating...\") false;\
- \n \$SendNotification2 ({ origin=\$0; \\\
- \n subject=([ \$SymbolForNotification \"sparkles\" ] . \"RouterOS u\
- pdate: \" . \$Update->\"latest-version\"); \\\
- \n message=(\"Seen a neighbor (\" . \$Neighbor . \") running versio\
- n \" . \$Update->\"latest-version\" . \\\
- \n \" from \" . \$Update->\"channel\" . \", updating on \" . \$Id\
- entity . \"...\"); link=\$Link; silent=true });\
- \n \$DoUpdate;\
- \n }\
- \n }\
- \n\
- \n :if ([ :len \$SafeUpdateUrl ] > 0) do={\
- \n :local Result;\
- \n :do {\
- \n :set Result [ /tool/fetch check-certificate=yes-without-crl \\\
- \n (\$SafeUpdateUrl . \$Update->\"channel\" . \"\?installed=\" . \
- \$Update->\"installed-version\" . \\\
- \n \"&latest=\" . \$Update->\"latest-version\") output=user as-va\
- lue ];\
- \n } on-error={\
- \n \$LogPrintExit2 warning \$0 (\"Failed receiving safe version for \
- \" . \$Update->\"channel\" . \".\") false;\
- \n }\
- \n :if (\$Result->\"status\" = \"finished\" && \$Result->\"data\" = \$U\
- pdate->\"latest-version\") do={\
- \n \$LogPrintExit2 info \$0 (\"Version \" . \$Update->\"latest-versio\
- n\" . \" is considered safe, updating...\") false;\
- \n \$SendNotification2 ({ origin=\$0; \\\
- \n subject=([ \$SymbolForNotification \"sparkles\" ] . \"RouterOS u\
- pdate: \" . \$Update->\"latest-version\"); \\\
- \n message=(\"Version \" . \$Update->\"latest-version\" . \" is con\
- sidered safe for \" . \$Update->\"channel\" . \\\
- \n \", updating on \" . \$Identity . \"...\"); link=\$Link; silen\
- t=true });\
- \n \$DoUpdate;\
- \n }\
- \n }\
- \n\
- \n :if ([ \$ScriptFromTerminal \$0 ] = true) do={\
- \n :put (\"Do you want to install RouterOS version \" . \$Update->\"lat\
- est-version\" . \"\? [y/N]\");\
- \n :if (([ /terminal/inkey timeout=60 ] % 32) = 25) do={\
- \n \$DoUpdate;\
- \n } else={\
- \n :put \"Canceled...\";\
- \n }\
- \n }\
- \n\
- \n :if (\$SentRouterosUpdateNotification = \$Update->\"latest-version\") \
- do={\
- \n \$LogPrintExit2 info \$0 (\"Already sent the RouterOS update notific\
- ation for version \" . \\\
- \n \$Update->\"latest-version\" . \".\") true;\
- \n }\
- \n\
- \n \$SendNotification2 ({ origin=\$0; \\\
- \n subject=([ \$SymbolForNotification \"sparkles\" ] . \"RouterOS updat\
- e: \" . \$Update->\"latest-version\"); \\\
- \n message=(\"A new RouterOS version \" . (\$Update->\"latest-version\"\
- ) . \\\
- \n \" is available for \" . \$Identity . \".\\n\\n\" . \\\
- \n [ \$DeviceInfo ]); link=\$Link; silent=true });\
- \n :set SentRouterosUpdateNotification (\$Update->\"latest-version\");\
- \n}\
- \n\
- \n:if (\$NumInstalled > \$NumLatest) do={\
- \n :if (\$SentRouterosUpdateNotification = \$Update->\"latest-version\") \
- do={\
- \n \$LogPrintExit2 info \$0 (\"Already sent the RouterOS downgrade noti\
- fication for version \" . \\\
- \n \$Update->\"latest-version\" . \".\") true;\
- \n }\
- \n\
- \n \$SendNotification2 ({ origin=\$0; \\\
- \n subject=([ \$SymbolForNotification \"warning-sign\" ] . \"RouterOS v\
- ersion: \" . \$Update->\"latest-version\"); \\\
- \n message=(\"A different RouterOS version \" . (\$Update->\"latest-ver\
- sion\") . \\\
- \n \" is available for \" . \$Identity . \", but it is a downgrade.\\\
- n\\n\" . \\\
- \n [ \$DeviceInfo ]); link=\$Link; silent=true });\
- \n \$LogPrintExit2 info \$0 (\"A different RouterOS version \" . (\$Updat\
- e->\"latest-version\") . \\\
- \n \" is available for downgrade.\") false;\
- \n :set SentRouterosUpdateNotification (\$Update->\"latest-version\");\
- \n}\
- \n"
- add dont-require-permissions=no name=dhcp-to-dns owner=dhcp-to-dns policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\
- !rsc by RouterOS\
- \n# RouterOS script: dhcp-to-dns\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md\
- \n#\
- \n# provides: lease-script, order=20\
- \n#\
- \n# check DHCP leases and add/remove/update DNS entries\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/doc/dhcp-to-dns.md\
- \n\
- \n:local 0 \"dhcp-to-dns\";\
- \n:global GlobalFunctionsReady;\
- \n:while (\$GlobalFunctionsReady != true) do={ :delay 500ms; }\
- \n\
- \n:global Domain;\
- \n:global Identity;\
- \n\
- \n:global CharacterReplace;\
- \n:global EitherOr;\
- \n:global IfThenElse;\
- \n:global LogPrintExit2;\
- \n:global LogPrintOnce;\
- \n:global ParseKeyValueStore;\
- \n:global ScriptLock;\
- \n\
- \n\$ScriptLock \$0 false 10;\
- \n\
- \n:local Ttl 5m;\
- \n:local CommentPrefix (\"managed by \" . \$0);\
- \n:local CommentString (\"--- \" . \$0 . \" above ---\");\
- \n\
- \n:if ([ :len [ /ip/dns/static/find where (name=\$CommentString or (commen\
- t=\$CommentString and name=-)) type=NXDOMAIN disabled ] ] = 0) do={\
- \n /ip/dns/static/add name=\$CommentString type=NXDOMAIN disabled=yes;\
- \n \$LogPrintExit2 warning \$0 (\"Added disabled static dns record with n\
- ame '\" . \$CommentString . \"'.\") false;\
- \n}\
- \n:local PlaceBefore ([ /ip/dns/static/find where (name=\$CommentString or\
- \_(comment=\$CommentString and name=-)) type=NXDOMAIN disabled ]->0);\
- \n\
- \n:foreach DnsRecord in=[ /ip/dns/static/find where comment~(\"^\" . \$Com\
- mentPrefix . \"\\\\b\") (!type or type=A) ] do={\
- \n :local DnsRecordVal [ /ip/dns/static/get \$DnsRecord ];\
- \n :local DnsRecordInfo [ \$ParseKeyValueStore (\$DnsRecordVal->\"comment\
- \") ];\
- \n :local MacInServer (\$DnsRecordInfo->\"macaddress\" . \" in \" . \$Dns\
- RecordInfo->\"server\");\
- \n\
- \n :if ([ :len [ /ip/dhcp-server/lease/find where active-mac-address=(\$D\
- nsRecordInfo->\"macaddress\") \\\
- \n active-address=(\$DnsRecordVal->\"address\") server=(\$DnsRecordI\
- nfo->\"server\") status=bound ] ] > 0) do={\
- \n \$LogPrintExit2 debug \$0 (\"Lease for \" . \$MacInServer . \" (\" .\
- \_\$DnsRecordVal->\"name\" . \") still exists. Not deleting record.\") fal\
- se;\
- \n } else={\
- \n :local Found false;\
- \n \$LogPrintExit2 info \$0 (\"Lease expired for \" . \$MacInServer . \
- \", deleting record (\" . \$DnsRecordVal->\"name\" . \").\") false;\
- \n /ip/dns/static/remove \$DnsRecord;\
- \n /ip/dns/static/remove [ find where type=CNAME comment=(\$DnsRecordVa\
- l->\"comment\") ];\
- \n }\
- \n}\
- \n\
- \n:foreach Lease in=[ /ip/dhcp-server/lease/find where status=bound ] do={\
- \n :local LeaseVal;\
- \n :do {\
- \n :set LeaseVal [ /ip/dhcp-server/lease/get \$Lease ];\
- \n :if ([ :len [ /ip/dhcp-server/lease/find where active-mac-address=(\
- \$LeaseVal->\"active-mac-address\") status=bound ] ] > 1) do={\
- \n \$LogPrintOnce info \$0 (\"Multiple bound leases found for mac-add\
- ress \" . (\$LeaseVal->\"active-mac-address\") . \"!\");\
- \n }\
- \n } on-error={\
- \n \$LogPrintExit2 debug \$0 (\"A lease just vanished, ignoring.\") fal\
- se;\
- \n }\
- \n\
- \n :if ([ :len (\$LeaseVal->\"active-address\") ] > 0) do={\
- \n :local Comment (\$CommentPrefix . \", macaddress=\" . \$LeaseVal->\"\
- active-mac-address\" . \", server=\" . \$LeaseVal->\"server\");\
- \n :local MacDash [ \$CharacterReplace (\$LeaseVal->\"active-mac-addres\
- s\") \":\" \"-\" ];\
- \n :local HostName [ \$CharacterReplace [ \$EitherOr ([ \$ParseKeyValue\
- Store (\$LeaseVal->\"comment\") ]->\"hostname\") (\$LeaseVal->\"host-name\
- \") ] \" \" \"\" ];\
- \n :local Network [ /ip/dhcp-server/network/find where (\$LeaseVal->\"a\
- ctive-address\") in address ];\
- \n :local NetworkVal;\
- \n :if ([ :len \$Network ] > 0) do={\
- \n :set NetworkVal [ /ip/dhcp-server/network/get (\$Network->0) ];\
- \n }\
- \n :local NetworkInfo [ \$ParseKeyValueStore (\$NetworkVal->\"comment\"\
- ) ];\
- \n :local NetDomain ([ \$IfThenElse ([ :len (\$NetworkInfo->\"name-extr\
- a\") ] > 0) (\$NetworkInfo->\"name-extra\" . \".\") ] . \\\
- \n [ \$EitherOr [ \$EitherOr (\$NetworkInfo->\"domain\") (\$NetworkVa\
- l->\"domain\") ] \$Domain ]);\
- \n :local FullA (\$MacDash . \".\" . \$NetDomain);\
- \n :local FullCN (\$HostName . \".\" . \$NetDomain);\
- \n :local MacInServer (\$LeaseVal->\"active-mac-address\" . \" in \" . \
- \$LeaseVal->\"server\");\
- \n\
- \n :local DnsRecord [ /ip/dns/static/find where comment=\$Comment (!typ\
- e or type=A) ];\
- \n :if ([ :len \$DnsRecord ] > 0) do={\
- \n :local DnsRecordVal [ /ip/dns/static/get \$DnsRecord ];\
- \n\
- \n :if (\$DnsRecordVal->\"address\" = \$LeaseVal->\"active-address\" \
- && \$DnsRecordVal->\"name\" = \$FullA) do={\
- \n \$LogPrintExit2 debug \$0 (\"The A record for \" . \$MacInServer\
- \_. \" (\" . \$FullA . \") does not need updating.\") false;\
- \n } else={\
- \n \$LogPrintExit2 info \$0 (\"Updating A record for \" . \$MacInSe\
- rver . \" (\" . \$FullA . \" -> \" . \$LeaseVal->\"active-address\" . \").\
- \") false;\
- \n /ip/dns/static/set address=(\$LeaseVal->\"active-address\") name\
- =\$FullA \$DnsRecord;\
- \n }\
- \n\
- \n :local CName [ /ip/dns/static/find where comment=\$Comment type=CN\
- AME ];\
- \n :if ([ :len \$CName ] > 0) do={\
- \n :local CNameVal [ /ip/dns/static/get \$CName ];\
- \n :if (\$CNameVal->\"name\" != \$FullCN || \$CNameVal->\"cname\" !\
- = \$FullA) do={\
- \n \$LogPrintExit2 info \$0 (\"Deleting CNAME record with wrong d\
- ata for \" . \$MacInServer . \".\") false;\
- \n /ip/dns/static/remove \$CName;\
- \n }\
- \n }\
- \n :if ([ :len \$HostName ] > 0 && [ :len [ /ip/dns/static/find where\
- \_name=\$FullCN type=CNAME ] ] = 0) do={\
- \n \$LogPrintExit2 info \$0 (\"Adding CNAME record for \" . \$MacIn\
- Server . \" (\" . \$FullCN . \" -> \" . \$FullA . \").\") false;\
- \n /ip/dns/static/add name=\$FullCN type=CNAME cname=\$FullA ttl=\$\
- Ttl comment=\$Comment place-before=\$PlaceBefore;\
- \n }\
- \n\
- \n } else={\
- \n \$LogPrintExit2 info \$0 (\"Adding A record for \" . \$MacInServer\
- \_. \" (\" . \$FullA . \" -> \" . \$LeaseVal->\"active-address\" . \").\")\
- \_false;\
- \n /ip/dns/static/add name=\$FullA type=A address=(\$LeaseVal->\"acti\
- ve-address\") ttl=\$Ttl comment=\$Comment place-before=\$PlaceBefore;\
- \n :if ([ :len \$HostName ] > 0 && [ :len [ /ip/dns/static/find where\
- \_name=\$FullCN type=CNAME ] ] = 0) do={\
- \n \$LogPrintExit2 info \$0 (\"Adding CNAME record for \" . \$MacIn\
- Server . \" (\" . \$FullCN . \" -> \" . \$FullA . \").\") false;\
- \n /ip/dns/static/add name=\$FullCN type=CNAME cname=\$FullA ttl=\$\
- Ttl comment=\$Comment place-before=\$PlaceBefore;\
- \n }\
- \n }\
- \n\
- \n :if ([ :len [ /ip/dns/static/find where name=\$FullA (!type or type=\
- A) ] ] > 1) do={\
- \n \$LogPrintOnce warning \$0 (\"The name '\" . \$FullA . \"' appeare\
- d in more than one A record!\");\
- \n }\
- \n } else={\
- \n \$LogPrintExit2 debug \$0 (\"No address available... Ignoring.\") fa\
- lse;\
- \n }\
- \n}\
- \n"
- add dont-require-permissions=no name=lease-script owner=lease-script policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\
- !rsc by RouterOS\
- \n# RouterOS script: lease-script\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md\
- \n#\
- \n# run scripts on DHCP lease\
- \n# https://git.eworm.de/cgit/routeros-scripts/about/doc/lease-script.md\
- \n\
- \n:local 0 \"lease-script\";\
- \n:global GlobalFunctionsReady;\
- \n:while (\$GlobalFunctionsReady != true) do={ :delay 500ms; }\
- \n\
- \n:global Grep;\
- \n:global IfThenElse;\
- \n:global LogPrintExit2;\
- \n:global ParseKeyValueStore;\
- \n:global ScriptLock;\
- \n\
- \n:if ([ :typeof \$leaseActIP ] = \"nothing\" || \\\
- \n [ :typeof \$leaseActMAC ] = \"nothing\" || \\\
- \n [ :typeof \$leaseServerName ] = \"nothing\" || \\\
- \n [ :typeof \$leaseBound ] = \"nothing\") do={\
- \n \$LogPrintExit2 error \$0 (\"This script is supposed to run from ip dh\
- cp-server.\") true;\
- \n}\
- \n\
- \n\$LogPrintExit2 debug \$0 (\"DHCP Server \" . \$leaseServerName . \" \" \
- . [ \$IfThenElse (\$leaseBound = 0) \\\
- \n \"de\" \"\" ] . \"assigned lease \" . \$leaseActIP . \" to \" . \$leas\
- eActMAC) false;\
- \n\
- \n\$ScriptLock \$0 false 10;\
- \n\
- \n:if ([ :len [ /system/script/job/find where script=\$0 ] ] > 1) do={\
- \n \$LogPrintExit2 debug \$0 (\"More invocations are waiting, exiting ear\
- ly.\") true;\
- \n}\
- \n\
- \n:local RunOrder ({});\
- \n:foreach Script in=[ /system/script/find where source~(\"\\n# provides: \
- lease-script\\\\b\") ] do={\
- \n :local ScriptVal [ /system/script/get \$Script ];\
- \n :local Store [ \$ParseKeyValueStore [ \$Grep (\$ScriptVal->\"source\")\
- \_(\"\\23 provides: lease-script, \") ] ];\
- \n\
- \n :set (\$RunOrder->(\$Store->\"order\" . \"-\" . \$ScriptVal->\"name\")\
- ) (\$ScriptVal->\"name\");\
- \n}\
- \n\
- \n:foreach Order,Script in=\$RunOrder do={\
- \n :do {\
- \n \$LogPrintExit2 debug \$0 (\"Running script with order \" . \$Order \
- . \": \" . \$Script) false;\
- \n /system/script/run \$Script;\
- \n } on-error={\
- \n \$LogPrintExit2 warning \$0 (\"Running script '\" . \$Script . \"' f\
- ailed!\") false;\
- \n }\
- \n}\
- \n"
- add dont-require-permissions=no name=WB_Up owner=liet policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\
- interface/wireguard/peers/enable [find where comment name=wildberries]"
- add dont-require-permissions=no name=WB_Down owner=liet policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\
- interface/wireguard/peers/disable [find where comment name=wildberries]"
- add dont-require-permissions=no name=Speedtest owner=liet-phone policy=\
- read,write,test,password source=":local txAvg 0 :local rxAvg 0 :local ts [\
- /system clock get time] :set ts ([:pick \$ts 0 2].[:pick \$ts 3 5].[:pick \
- \$ts 6 8]) :local ds [/system clock get date] :set ds ([:pick \$ds 7 11].[\
- :pick \$ds 0 3].[:pick \$ds 4 6]) tool bandwidth-test protocol=tcp directi\
- on=transmit address=ip_bandsw_test_server duration=5s do={ :set txAvg (\$\
- \"tx-total-average\" / 1048576 ); } tool bandwidth-test protocol=tcp direc\
- tion=receive address=ip_bandsw_test_server duration=5s do={ :set rxAvg (\$\
- \"rx-total-average\" / 1048576 ); } :local ContentsFile [/file get isp-qua\
- lity.txt contents]; /file set isp-quality.txt contents=\"\$ContentsFile\\n\
- \$ds-\$ts tx: \$txAvg Mbps - rx: \$rxAvg Mbps\""
- add dont-require-permissions=no name=steedtest owner=liet-phone policy=\
- read,write,policy,test,password source=":local txAvg 0 :local rxAvg 0 :loc\
- al ts [/system clock get time] :set ts ([:pick \$ts 0 2].[:pick \$ts 3 5].\
- [:pick \$ts 6 8]) :local ds [/system clock get date] :set ds ([:pick \$ds \
- 7 11].[:pick \$ds 0 3].[:pick \$ds 4 6]) tool bandwidth-test protocol=tcp \
- direction=transmit address=ip_bandsw_test_server duration=5s do={ :set txA\
- vg (\$\"tx-total-average\" / 1048576 ); } tool bandwidth-test protocol=tcp\
- \_direction=receive address=ip_bandsw_test_server duration=5s do={ :set rx\
- Avg (\$\"rx-total-average\" / 1048576 ); } :local ContentsFile [/file get \
- isp-quality.txt contents]; /file set isp-quality.txt contents=\"\$Contents\
- File\\n\$ds-\$ts tx: \$txAvg Mbps - rx: \$rxAvg Mbps\""
- add dont-require-permissions=no name=speedtest owner=liet-phone policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\
- local txAvg 0\
- \n:local rxAvg 0\
- \n\
- \n:local ts [/system clock get time]\
- \n:set ts ([:pick \$ts 0 2].[:pick \$ts 3 5].[:pick \$ts 6 8])\
- \n\
- \n:local ds [/system clock get date]\
- \n:set ds ([:pick \$ds 7 11].[:pick \$ds 0 3].[:pick \$ds 4 6])\
- \n\
- \ntool bandwidth-test protocol=tcp direction=transmit address=ip_bandsw_te\
- st_server duration=5s do={\
- \n:set txAvg (\$\"tx-total-average\" / 1048576 );\
- \n}\
- \n\
- \ntool bandwidth-test protocol=tcp direction=receive address=ip_bandsw_tes\
- t_server duration=5s do={\
- \n:set rxAvg (\$\"rx-total-average\" / 1048576 );\
- \n}\
- \n\
- \n:local ContentsFile [/file get isp-quality.txt contents];\
- \n/file set isp-quality.txt contents=\"\$ContentsFile\\n\$ds-\$ts tx: \$tx\
- Avg Mbps - rx: \$rxAvg Mbps\""
- add dont-require-permissions=no name=script1 owner=liet-phone policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="{\
- \n:local minimalMtu 1600\
- \n\
- \n:local mtuCheck do={\
- \n :if ([/interface get \$1 l2mtu] < \$2) do={\
- \n :put (\"Interface \" . [/interface get \$1 name] . \" has MTU under \
- \" . \$2)\
- \n }\
- \n}\
- \n\
- \n# ethernet\
- \n:foreach i in=[/interface ethernet find running] do={\
- \n \$mtuCheck \$i \$minimalMtu\
- \n}\
- \n\
- \n# wireless\
- \n:foreach i in=[/interface wireless find disabled=no] do={\
- \n \$mtuCheck \$i \$minimalMtu\
- \n}\
- \n}"
- add dont-require-permissions=no name=script2 owner=liet-phone policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="{\
- \n:local minimalMtu 1600\
- \n\
- \n:local mtuCheck do={\
- \n :if ([/interface get \$1 l2mtu] < \$2) do={\
- \n :put (\"Interface \" . [/interface get \$1 name] . \" has MTU under \
- \" . \$2)\
- \n }\
- \n}\
- \n\
- \n# ethernet\
- \n:foreach i in=[/interface ethernet find running] do={\
- \n \$mtuCheck \$i \$minimalMtu\
- \n}\
- \n\
- \n# wireless\
- \n:foreach i in=[/interface wireless find disabled=no] do={\
- \n \$mtuCheck \$i \$minimalMtu\
- \n}\
- \n}"
- add dont-require-permissions=no name=dhcp2dns.rsc owner=liet policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\
- local DHCPtag \"#*# Created by DHCP2DNS #*#\"\r\
- \n:local LogPrefix \"DHCP2DNS (\$leaseServerName)\"\r\
- \n\r\
- \n###\r\
- \n# Functions\r\
- \n\r\
- \n# remove \\0 and spaces from string passed as inStr=<string>\r\
- \n:local trimString do=\\\r\
- \n{\r\
- \n :local outStr\r\
- \n :for i from=0 to=([:len \$inStr] - 1) do=\\\r\
- \n {\r\
- \n :local tmp [:pick \$inStr \$i];\r\
- \n :if ((\$tmp !=\" \") and (\$tmp !=\"\\00\")) do=\\\r\
- \n {\r\
- \n :set outStr (\$outStr . \$tmp)\r\
- \n }\r\
- \n }\r\
- \n :return \$outStr\r\
- \n}\r\
- \n\r\
- \n# \"a.b.c.d\" -> \"a-b-c-d\" for IP addresses used as replacement for mi\
- ssing host names\r\
- \n:local ip2Host do=\\\r\
- \n{\r\
- \n :local outStr\r\
- \n :for i from=0 to=([:len \$inStr] - 1) do=\\\r\
- \n {\r\
- \n :local tmp [:pick \$inStr \$i];\r\
- \n :if (\$tmp =\".\") do=\\\r\
- \n {\r\
- \n :set tmp \"-\"\r\
- \n }\r\
- \n :set outStr (\$outStr . \$tmp)\r\
- \n }\r\
- \n :return \$outStr\r\
- \n}\r\
- \n\r\
- \n###\r\
- \n# Script entry point\r\
- \n#\r\
- \n# Expected environment variables:\r\
- \n# leaseBound 1 = lease bound, 0 = lease removed\r\
- \n# leaseServerName Name of DHCP server\r\
- \n# leaseActIP IP address of DHCP client\r\
- \n\r\
- \n:if ( [ :len \$leaseActIP ] <= 0 ) do=\\\r\
- \n{\r\
- \n :log error \"\$LogPrefix: empty lease address\"\r\
- \n :error \"empty lease address\"\r\
- \n}\r\
- \n\r\
- \n:if ( \$leaseBound = 1 ) do=\\\r\
- \n{\r\
- \n # new DHCP lease added\r\
- \n \r\
- \n /ip dhcp-server\r\
- \n :local ttl [ get [ find name=\$leaseServerName ] lease-time ]\r\
- \n network \r\
- \n :local domain [ get [ find \$leaseActIP in address ] domain ]\r\
- \n :set domain [ \$trimString inStr=\$domain ]\r\
- \n\r\
- \n .. lease\r\
- \n :local leaseId [ find address=\$leaseActIP ]\r\
- \n\r\
- \n # Check for multiple active leases for the same IP address. It's weird\
- \_and it shouldn't be, but just in case.\r\
- \n :if ( [ :len \$leaseId ] != 1) do=\\\r\
- \n {\r\
- \n :log warning \"\$LogPrefix: Multiple active DHCP leases for '\$lease\
- ActIP' (\?\?\?)\"\r\
- \n :error \"Multiple active DHCP leases for '\$leaseActIP' (\?\?\?)\"\r\
- \n } \r\
- \n :local hostname [ get \$leaseId host-name ]\r\
- \n :set hostname [ \$trimString inStr=\$hostname ]\r\
- \n\r\
- \n :if ( [ :len \$hostname ] <= 0 ) do=\\\r\
- \n {\r\
- \n :set hostname [ \$ip2Host inStr=\$leaseActIP ]\r\
- \n :log info \"\$LogPrefix: Empty hostname for '\$leaseActIP', using ge\
- nerated host name '\$hostname'\"\r\
- \n }\r\
- \n :if ( [ :len \$domain ] <= 0 ) do=\\\r\
- \n {\r\
- \n :log warning \"\$LogPrefix: Empty domainname for '\$leaseActIP', can\
- not create static DNS name\"\r\
- \n :error \"Empty domainname for '\$leaseActIP'\"\r\
- \n }\r\
- \n\r\
- \n :local fqdn (\$hostname . \".\" . \$domain)\r\
- \n\r\
- \n /ip dns static\r\
- \n :if ( [ :len [ find name=\$fqdn and address=\$leaseActIP and disabled=\
- no ] ] = 0 ) do=\\\r\
- \n {\r\
- \n add address=\$leaseActIP name=\$fqdn ttl=\$ttl comment=\$DHCPtag dis\
- abled=no\r\
- \n :log info \"\$LogPrefix: Static domain name '\$fqdn' created for '\$\
- leaseActIP' with ttl '\$ttl'\"\r\
- \n }\\\r\
- \n else=\\\r\
- \n {\r\
- \n :log warning \"\$LogPrefix: '\$fqdn' already exists, cannot create s\
- tatic DNS name for '\$leaseActIP'\"\r\
- \n :error \"\$LogPrefix: '\$fqdn' already exists\"\r\
- \n }\r\
- \n}\\\r\
- \nelse=\\\r\
- \n{\r\
- \n # DHCP lease removed\r\
- \n\r\
- \n /ip dns static\r\
- \n :local dnsDhcpId\r\
- \n :set dnsDhcpId [ find address=\$leaseActIP and comment=\$DHCPtag ]\r\
- \n :if ( [ :len \$dnsDhcpId ] > 0 ) do=\\\r\
- \n {\r\
- \n remove \$dnsDhcpId\r\
- \n :log info \"\$LogPrefix: Static DNS name(s) for '\$leaseActIP' remov\
- ed\"\r\
- \n }\r\
- \n}"
- add dont-require-permissions=no name=dhcp2 owner=liet policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\
- \_MikroTik (RouterOS) script for automatically setting DNS records\r\
- \n\r\
- \n# for clients when they obtain a DHCP lease.\r\
- \n\r\
- \n#\r\
- \n\r\
- \n# author SmartFinn <https://gist.github.com/SmartFinn>\r\
- \n\r\
- \n# based on https://github.com/karrots/ROS-DDNS\r\
- \n\r\
- \n:local domain;\r\
- \n\r\
- \n:local fqdn;\r\
- \n\r\
- \n:local hostname;\r\
- \n\r\
- \n:local safeHostname;\r\
- \n\r\
- \n:local token \"\$leaseServerName-\$leaseActMAC\";\r\
- \n\r\
- \n:local ttl [/ip dhcp-server get \$leaseServerName lease-time];\r\
- \n\r\
- \n# Getting the domain name from DHCP server. If a domain name is not\r\
- \n\r\
- \n# specified will use hostname only\r\
- \n\r\
- \n/ip dhcp-server network {\r\
- \n\r\
- \n:do {\r\
- \n\r\
- \n:set domain [get [find where (\$leaseActIP in address)] domain];\r\
- \n\r\
- \n# Add a dot before domain name\r\
- \n\r\
- \n:set domain (\".\" . \$domain);\r\
- \n\r\
- \n} on-error={\r\
- \n\r\
- \n:set domain \"\";\r\
- \n\r\
- \n};\r\
- \n\r\
- \n};\r\
- \n\r\
- \n:if (\$leaseBound = 1) do={\r\
- \n\r\
- \n:log debug \"\$leaseServerName: Processing bound lease \$leaseActMAC (\$\
- leaseActIP)\";\r\
- \n\r\
- \n/ip dhcp-server lease {\r\
- \n\r\
- \n:set hostname [get [find active-mac-address=\$leaseActMAC] host-name];\r\
- \n\r\
- \n};\r\
- \n\r\
- \n# Delete unallowed chars from the hostname\r\
- \n\r\
- \n:for i from=0 to=([:len \$hostname]-1) do={\r\
- \n\r\
- \n:local char [:pick \$hostname \$i];\r\
- \n\r\
- \n:if (\$char~\"[a-zA-Z0-9-]\") do={\r\
- \n\r\
- \n:set safeHostname (\$safeHostname . \$char);\r\
- \n\r\
- \n};\r\
- \n\r\
- \n};\r\
- \n\r\
- \n:if ([:len \$safeHostname] > 0) do={\r\
- \n\r\
- \n:set fqdn (\$safeHostname . \$domain);\r\
- \n\r\
- \n/ip dns static {\r\
- \n\r\
- \n:local itemId [find name=\$fqdn];\r\
- \n\r\
- \n:if (\$itemId != \"\") do={\r\
- \n\r\
- \n# This DNS entry already exists\r\
- \n\r\
- \n:if ([get \$itemId comment] = \$token) do={\r\
- \n\r\
- \n:if ([get \$itemId address] != \$leaseActIP) do={\r\
- \n\r\
- \nset \$itemId address=\$leaseActIP ttl=\$ttl;\r\
- \n\r\
- \n:log info \"Update DNS entry: \$fqdn -> \$leaseActIP (\$leaseActMAC)\";\
- \r\
- \n\r\
- \n};\r\
- \n\r\
- \n} else={\r\
- \n\r\
- \n:log warning \"Cannot to add DNS entry. \$fqdn already exists\";\r\
- \n\r\
- \n};\r\
- \n\r\
- \n} else={\r\
- \n\r\
- \n# Add DNS entry if it does not exist\r\
- \n\r\
- \nadd name=\$fqdn address=\$leaseActIP ttl=\$ttl comment=\$token;\r\
- \n\r\
- \n:log info \"Add DNS entry: \$fqdn -> \$leaseActIP (\$leaseActMAC)\";\r\
- \n\r\
- \n};\r\
- \n\r\
- \n};\r\
- \n\r\
- \n};\r\
- \n\r\
- \n} else={\r\
- \n\r\
- \n# Remove entry when lease expires (\$leaseBound=0)\r\
- \n\r\
- \n:log debug \"\$leaseServerName: Processing deassigned lease \$leaseActMA\
- C (\$leaseActIP)\";\r\
- \n\r\
- \n/ip dns static {\r\
- \n\r\
- \n:local itemId [find comment=\$token];\r\
- \n\r\
- \n:if (\$itemId != \"\") do={\r\
- \n\r\
- \n:set fqdn ([get \$itemId name]);\r\
- \n\r\
- \nremove \$itemId;\r\
- \n\r\
- \n:log info \"Remove DNS entry: \$fqdn -> \$leaseActIP (\$leaseActMAC)\";\
- \r\
- \n\r\
- \n};\r\
- \n\r\
- \n};\r\
- \n\r\
- \n};"
- add dont-require-permissions=no name=resetDhcpToStaticDns owner=liet policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\
- \n\
- \n:local DHCPtag\
- \n:local topdomain;\
- \n:local hostname;\
- \n:local hostip;\
- \n:local skip;\
- \n:local protected;\
- \n:local ttl\
- \n:local leaseServerName\
- \n\
- \n:set DHCPtag \"#DHCP\"\
- \n:set leaseServerName \"defconf\"\
- \n:set topdomain \"put_your_top_domain_here.\"\
- \n\
- \n/ip dhcp-server\
- \n:set ttl [ get [ find name=\$leaseServerName ] lease-time ]\
- \n \
- \n\
- \n/ip dhcp-server lease;\
- \n:foreach i in=[find where status=\"bound\"] do={\
- \n /ip dhcp-server lease;\
- \n :if ([:len [get \$i host-name]] > 0) do={\
- \n :set hostname ([get \$i host-name] . \".\" . \$topdomain);\
- \n :set hostip [get \$i address];\
- \n /ip dns static;\
- \n# Remove if DNS entry already exist\
- \n:set protected false;\
- \n:set skip false;\
- \n :foreach di in [find] do={\
- \n :if ([get \$di name] = \$hostname) do={\
- \n:if ([get \$di comment] = \$DHCPtag) do={\
- \n:if ([get \$di address] = \$hostip) do={\
- \n:put (\"Unchanged: \" . \$hostname . \" : \" . \$hostip);\
- \n:set skip true;\
- \n} else={\
- \n:put (\"Removing: \" . \$hostname . \" : \" . \$hostip);\
- \n}\
- \nremove \$di;\
- \n} else={\
- \n:set protected true;\
- \n:put (\"Protected: \" . \$hostname . \" : \" . \$hostip);\
- \n}\
- \n }\
- \n }\
- \n:if (!\$skip && !\$protected) do={\
- \n# Add DNS entry\
- \n:put (\"Adding: \" . \$hostname . \" : \" . \$hostip);\
- \n/ip dns static add name=\$hostname address=\$hostip ttl=\$ttl comment=\$\
- DHCPtag;\
- \n}\
- \n }\
- \n}\
- \n\
- \n"
- add dont-require-permissions=no name=st owner=liet policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\
- log info \"------------ BW-TEST Starts--------------\";\r\
- \n\r\
- \n:local luser \"BW Test Server USER\";\r\
- \n:local lpass \"BW TEST Server PASSWORD\";\r\
- \n:local Addr \"BW TEST Server IP ADDRESS\";\r\
- \n\r\
- \n:local avrRX 0;\r\
- \n:local avrTX 0;\r\
- \n\r\
- \n\r\
- \n# DOWNLOAD TEST\r\
- \n:log info \"----> Measuring RX (30 seg)........\";\r\
- \n:do {/tool\r\
- \n bandwidth-test duration=30s user=\$luser password=\$lpass protocol=tc\
- p address=\$Addr direction=receive do={\r\
- \n :set \$avrRX (\"rx-total-average: \" . (\$\"rx-total-average\" / 10\
- 48576) . \".\" . (\$\"rx-total-average\" % (1048576) / 1024) . \" Mbps\" )\
- ;\r\
- \n }\r\
- \n} on-error={:log error message=\"RX script failed\"}\r\
- \n\r\
- \n:delay 2s;\r\
- \n\r\
- \n# UPLOAD TEST\r\
- \n:log info \"----> Measuring TX (30 seg) ........\";\r\
- \n:do {/tool\r\
- \n bandwidth-test duration=30s user=\$luser password=\$lpass protocol=tcp\
- \_address=\$Addr direction=transmit do={\r\
- \n :set \$avrTX (\"tx-total-average: \" . (\$\"tx-total-average\" / 10\
- 48576) . \".\" . (\$\"tx-total-average\" % (1048576) / 1024) . \" Mbps\" )\
- ;\r\
- \n }\r\
- \n} on-error={:log error message=\"TX script failed\"}\r\
- \n\r\
- \n:log info message=\$avrRX;\r\
- \n:log info message=\$avrTX;\r\
- \n:log info \"-------- End of BW-TEST------------\";\r\
- \n\r\
- \n\r\
- \n################# SAVING RESULTS WITH DATE ######################\r\
- \n:local filename2 \"LOG_BW_TEST.txt\"\r\
- \n:local ds [/system clock get date];\r\
- \n:local months (\"jan\",\"feb\",\"mar\",\"apr\",\"may\",\"jun\",\"jul\",\
- \"aug\",\"sep\",\"oct\",\"nov\",\"dec\");\r\
- \n:local month [ :pick \$ds 0 3 ];\r\
- \n:local mm ([ :find \$months \$month -1 ] + 1);\r\
- \n:if (\$mm < 10) do={ :set mm (\"0\" . \$mm); };\r\
- \n:set ds ([:pick \$ds 7 11] . \$mm . [:pick \$ds 4 6]);\r\
- \n\r\
- \n:if ( [:len [/file find name=\$filename2]] = 0) do={\r\
- \n:log info \"Log file does not exist. Creating a new one.....\";\r\
- \n/file print file=\$filename2 where name=\"\";\r\
- \n}\r\
- \n\r\
- \n:log info \"Adding result to the end of the lof file......\";\r\
- \n/file set \$filename2 contents=([get \$filename2 contents] .\"\\n\".\$d\
- s.\"-->\" . \$avrRX);\r\
- \n/file set \$filename2 contents=([get \$filename2 contents] .\" \". \$\
- avrTX);\r\
- \n}"
- add dont-require-permissions=no name=dns owner=liet policy=\
- ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\
- \_set variables\r\
- \n:local primaryDNS \"192.168.254.250\";\r\
- \n:local fallbackDNS \"1.1.1.1\";\r\
- \n:local currentDNS;\r\
- \n:set \$currentDNS [/ip dns get servers];\r\
- \n#:log warning \"What I got is: \$currentDNS\"\r\
- \n#:log warning \"What I want to see is: \$primaryDNS\"\r\
- \n:do {\r\
- \n:put [resolve google.com server=\$primaryDNS];\r\
- \nif (\$currentDNS!=\$primaryDNS) do={\r\
- \n:log warning \"DNS Failover: Switching to primaryDNS\";\r\
- \n/ip dns set servers \$primaryDNS\r\
- \nip/dns/set allow-remote-requests=no;\r\
- \n/ip/dns/set use-doh-server=\"https://main.mentat.su/dns-query\";\r\
- \n/ip dhcp-server network set 0 dns-server=192.168.254.250;\r\
- \n} else={}\r\
- \n} on-error={ :set \$currentDNS [/ip dns get servers];\r\
- \nif (\$currentDNS!=\$fallbackDNS) do={\r\
- \n:log error \"DNS Failover: Switching to FallbackDNS\";\r\
- \n/ip dns set servers \$fallbackDNS\r\
- \n/ip dhcp-server network set 0 dns-server=1.1.1.1;\r\
- \n/ip/dns/set allow-remote-requests=yes;\r\
- \n/ip/dns/set use-doh-server=\"https://8.8.8.8/dns-query\";\r\
- \n} else={:log info \"Using Failover DNS, Primary Unavailable\"}\r\
- \n}\r\
- \n#try to reach google through the primaryDNS\r\
- \n#if it works and we are on a different DNS, set the DNS server to the pr\
- imaryDNS\r\
- \n#if it works and we are already on the primaryDNS, do nothing\r\
- \n#if we can't reach google and we aren't already on our FallbackDNS, swit\
- ch to fallback\r\
- \n#if we can't reach google through primaryDNS and we are on the fallback,\
- \_log that primaryDNS is unavailable"
- /tool graphing interface
- add
- /tool graphing resource
- add
- /tool netwatch
- add disabled=no down-script="" host=192.168.254.250 http-codes="" \
- test-script="" type=simple up-script=""
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement