# ============================================================ # Cloud Hotspot Manager — RouterOS 6.x เท่านั้น # ถ้าเครื่องเป็น RouterOS 7 ให้กลับไปเลือกแท็บ RouterOS 7.x # ============================================================ /system identity set name="{{IDENTITY}}" /radius remove numbers=[/radius find] /radius add service=hotspot address={{SERVER}} secret={{SECRET}} timeout=3s /system scheduler remove numbers=[/system scheduler find name="kickuser"] /system schedule add name=kickuser on-event=":global nas [/sys id get name]\n\r\n:global nas [/sys id get name]\n\r\n:global version [/system resource get version]\n\r\n:global version [:pick \$version 0 [:find \$version \" \"]]\n\r\n:global model [/system resource get board-name]\n\r\n:global msp [:find \$model \" \"]\n\r\n:if ([:typeof \$msp] = \"num\") do={:set model [:pick \$model 0 \$msp]}\n\r\n:global cpu [/system resource get cpu-load]\n\r\n:global cputemp 0\n\r\n:do {:set cputemp [/system health get cpu-temperature]} on-error={}\n\r\n:global hardwaretemp 0\n\r\n:do {:set hardwaretemp [/system health get temperature]} on-error={}\n\r\n:global uptime [/system resource get uptime]\n\r\n:global useractive [/ip hotspot active print count-only]\n\r\n:delay 3\n\r\n/tool fetch url=\"https://{{HOST}}/fetch/index/{{TOKEN}}/\$model/\$version/\$cpu/\$uptime/\$useractive/\$cputemp/\$hardwaretemp\" mode=http dst-path=disconnect.rsc;\n\r\ndelay 3;\n\r\n/import disconnect.rsc;\n\r\ndelay 3;\n\r\n/file remove disconnect.rsc" interval=1m /ip hotspot profile set use-radius=yes radius-accounting=yes login-by=http-chap,http-pap,mac-cookie numbers=[/ip hotspot profile find name=hsprof1] /ip hotspot walled-garden ip add action=accept disabled=no dst-address="{{SERVER}}" /ip hotspot walled-garden ip add action=accept disabled=no dst-host="{{HOST}}" /ip hotspot walled-garden add action=allow disabled=no dst-host=*.fbcdn.net comment=*.xx.fbcdn.net /ip hotspot user profile set shared-users="" numbers=0 if ([/file print count-only where name="flash"]=1) do={/file set flash/hotspot/login.html contents="<html><head><title>...</title></head><body>\$(if chap-id)<noscript><center><b>JavaScript required. Enable JavaScript to continue.</b></center></noscript>\$(endif)<center>If you are not redirected in a few seconds, click \"continue\" below<br><form name=\"redirect\" action=\"https://{{HOST}}/auth/login.php\" method=\"post\"><input type=\"hidden\" name=\"mac\" value=\"\$(mac)\"><input type=\"hidden\" name=\"ip\" value=\"\$(ip)\"><input type=\"hidden\" name=\"username\" value=\"\$(username)\"><input type=\"hidden\" name=\"link-login\" value=\"\$(link-login)\"><input type=\"hidden\" name=\"link-logout\" value=\"\$(link-logout)\"><input type=\"hidden\" name=\"link-orig\" value=\"\$(link-orig)\"><input type=\"hidden\" name=\"error\" value=\"\$(error)\"><input type=\"hidden\" name=\"chap-id\" value=\"\$(chap-id)\"><input type=\"hidden\" name=\"chap-challenge\" value=\"\$(chap-challenge)\"><input type=\"hidden\" name=\"link-login-only\" value=\"\$(link-login-only)\"><input type=\"hidden\" name=\"link-orig-esc\" value=\"\$(link-orig-esc)\"><input type=\"hidden\" name=\"mac-esc\" value=\"\$(mac-esc)\"><input type=\"hidden\" name=\"identity\" value=\"\$(identity)\"><input type=\"submit\" value=\"continue\"></form><script language=\"JavaScript\">document.redirect.submit();</script></center></body></html>";} else {/file set hotspot/login.html contents="<html><head><title>...</title></head><body>\$(if chap-id)<noscript><center><b>JavaScript required. Enable JavaScript to continue.</b></center></noscript>\$(endif)<center>If you are not redirected in a few seconds, click \"continue\" below<br><form name=\"redirect\" action=\"https://{{HOST}}/auth/login.php\" method=\"post\"><input type=\"hidden\" name=\"mac\" value=\"\$(mac)\"><input type=\"hidden\" name=\"ip\" value=\"\$(ip)\"><input type=\"hidden\" name=\"username\" value=\"\$(username)\"><input type=\"hidden\" name=\"link-login\" value=\"\$(link-login)\"><input type=\"hidden\" name=\"link-logout\" value=\"\$(link-logout)\"><input type=\"hidden\" name=\"link-orig\" value=\"\$(link-orig)\"><input type=\"hidden\" name=\"error\" value=\"\$(error)\"><input type=\"hidden\" name=\"chap-id\" value=\"\$(chap-id)\"><input type=\"hidden\" name=\"chap-challenge\" value=\"\$(chap-challenge)\"><input type=\"hidden\" name=\"link-login-only\" value=\"\$(link-login-only)\"><input type=\"hidden\" name=\"link-orig-esc\" value=\"\$(link-orig-esc)\"><input type=\"hidden\" name=\"mac-esc\" value=\"\$(mac-esc)\"><input type=\"hidden\" name=\"identity\" value=\"\$(identity)\"><input type=\"submit\" value=\"continue\"></form><script language=\"JavaScript\">document.redirect.submit();</script></center></body></html>";} if ([/file print count-only where name="flash"]=1) do={/file set flash/hotspot/logout.html contents="<html><head><title></title><meta http-equiv=\"Content-Type\" content=text/html; charset=utf-8\"><meta http-equiv=\"refresh\" content=\"0; URL=\$(link-login)\"></body></html>";} else {/file set hotspot/logout.html contents="<html><head><title></title><meta http-equiv=\"Content-Type\" content=text/html; charset=utf-8\"><meta http-equiv=\"refresh\" content=\"0; URL=\$(link-login)\"></body></html>";}
# ============================================================ # Cloud Hotspot Manager - RouterOS 7.x # Paste the whole block into Terminal once. Safe to re-run. # # A hotspot server must exist first. If not, run: # /ip hotspot setup # ...then paste this script. # # NOTE: ASCII only on purpose. Some RouterOS terminals truncate a # paste containing non-ASCII text, which leaves the scheduler # half-written and the heartbeat never runs. # ============================================================ :put "=== Cloud Hotspot Manager: start ===" # ---------- require a hotspot server ---------- :if ([:len [/ip hotspot find]] = 0) do={ :put "!! No hotspot server found. Run /ip hotspot setup first, then paste this again." :error "no hotspot server" } /system identity set name="{{IDENTITY}}" # ---------- RADIUS ---------- /radius remove [find comment="cloud-hotspot"] /radius add service=hotspot address={{SERVER}} secret="{{SECRET}}" timeout=3s comment="cloud-hotspot" /radius incoming set accept=yes port=3799 # ---------- hotspot profile actually in use ---------- # (not [find default=yes] - many boxes use a profile named hsprof1) :foreach hs in=[/ip hotspot find] do={ :local pf [/ip hotspot get $hs profile] /ip hotspot profile set $pf use-radius=yes radius-accounting=yes \ radius-interim-update=received nas-port-type=wireless-802.11 \ login-by=http-pap,mac-cookie :put ("hotspot profile configured: " . $pf) } # simultaneous devices are enforced by the server, keep the router open :foreach up in=[/ip hotspot user profile find] do={ /ip hotspot user profile set $up shared-users=10 keepalive-timeout=2m idle-timeout=5m } # ---------- walled garden ---------- /ip hotspot walled-garden ip remove [find comment="cloud-hotspot"] /ip hotspot walled-garden remove [find comment="cloud-hotspot"] /ip hotspot walled-garden ip add action=accept dst-address={{SERVER}} comment="cloud-hotspot" /ip hotspot walled-garden add action=allow dst-host="{{HOST}}" comment="cloud-hotspot" {{GARDEN}} # ---------- heartbeat every minute + pick up disconnect commands ---------- # remove leftovers from older scripts (kickuser errors every minute if left) /system scheduler remove [find name="kickuser"] :do {/file remove [find name="disconnect.rsc"]} on-error={} /system scheduler remove [find name="cloudsync"] /system scheduler add name=cloudsync interval=1m start-time=startup on-event=":local ver [/system resource get version]; :local sp [:find \$ver \" \"]; :if ([:typeof \$sp] = \"num\") do={:set ver [:pick \$ver 0 \$sp]}; :local mdl [/system resource get board-name]; :local cpu [/system resource get cpu-load]; :local upt [/system resource get uptime]; :local act 0; :do {:set act [/ip hotspot active print count-only]} on-error={}; :do {/file remove [find name=\"cloudsync.rsc\"]} on-error={}; :do {/tool fetch url=\"{{BASE}}/fetch/status/{{TOKEN}}\" http-method=post http-data=(\"model=\" . \$mdl . \"&version=\" . \$ver . \"&cpu=\" . \$cpu . \"&uptime=\" . \$upt . \"&active=\" . \$act) check-certificate=no dst-path=cloudsync.rsc; :delay 2s; :do {/import cloudsync.rsc} on-error={}; :do {/file remove [find name=\"cloudsync.rsc\"]} on-error={}; :log info \"cloudsync: sent ok\"} on-error={:log warning \"cloudsync: cannot reach server - check internet and walled-garden\"}" # ---------- point the hotspot login page at the cloud portal ---------- # find the html-directory of the profile in use, then overwrite login/logout :local dir "" :foreach hs in=[/ip hotspot find] do={ :set dir [/ip hotspot profile get [/ip hotspot get $hs profile] html-directory] } :if ([:len $dir] = 0) do={:set dir "hotspot"} :local lp ($dir . "/login.html") :local lo ($dir . "/logout.html") :if ([:len [/file find name=$lp]] = 0) do={ :put ("!! " . $lp . " not found. Run /ip hotspot reset-html then paste this script again.") } else={ /file set [find name=$lp] contents="<html><head><title>...</title><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"></head><body>\$(if chap-id)<noscript><center><b>JavaScript required. Enable JavaScript to continue.</b></center></noscript>\$(endif)<center>Redirecting...<br><form name=\"redirect\" action=\"{{BASE}}/auth/login.php\" method=\"post\"><input type=\"hidden\" name=\"mac\" value=\"\$(mac)\"><input type=\"hidden\" name=\"ip\" value=\"\$(ip)\"><input type=\"hidden\" name=\"username\" value=\"\$(username)\"><input type=\"hidden\" name=\"link-login\" value=\"\$(link-login)\"><input type=\"hidden\" name=\"link-login-only\" value=\"\$(link-login-only)\"><input type=\"hidden\" name=\"link-orig\" value=\"\$(link-orig)\"><input type=\"hidden\" name=\"link-orig-esc\" value=\"\$(link-orig-esc)\"><input type=\"hidden\" name=\"error\" value=\"\$(error)\"><input type=\"hidden\" name=\"chap-id\" value=\"\$(chap-id)\"><input type=\"hidden\" name=\"chap-challenge\" value=\"\$(chap-challenge)\"><input type=\"hidden\" name=\"mac-esc\" value=\"\$(mac-esc)\"><input type=\"hidden\" name=\"identity\" value=\"\$(identity)\"><input type=\"submit\" value=\"continue\"></form><script language=\"JavaScript\">document.redirect.submit();</script></center></body></html>" :put ("login page written: " . $lp) } :if ([:len [/file find name=$lo]] > 0) do={ /file set [find name=$lo] contents="<html><head><meta http-equiv=\"refresh\" content=\"0; url=\$(link-login)\"></head><body></body></html>" } # ---------- send status now instead of waiting a minute ---------- :do {/system scheduler run cloudsync} on-error={} :delay 3s :put "=== done - open the Router page in the web UI and check status ===" # ---------- troubleshooting ---------- # /system scheduler print detail where name=cloudsync # /log print where message~"cloudsync" # /radius monitor 0 # /ip hotspot active print # manual test from the router: # /tool fetch url="{{BASE}}/fetch/status/{{TOKEN}}" http-method=post http-data="model=manual&version=7&cpu=1&uptime=1d00:00:00&active=0&cputemp=0&hwtemp=0" check-certificate=no dst-path=t.rsc # /log print where topics~"script"