Created
May 1, 2020 16:45
-
-
Save ylxdzsw/1eac8713c343ee935cbcf3f3d5be71c9 to your computer and use it in GitHub Desktop.
A failed attempt to abuse cloudflare workers as a web monitor.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| serverchan_token = '' | |
| telegram_token = '' | |
| telegram_chatid = '' | |
| secret = '' # it also acts as instance ID. Change this everytime you restart the script. | |
| host1 = '' | |
| host2 = '' # we need two hosts because of https://community.cloudflare.com/t/issue-with-worker-to-worker-https-request/94472 | |
| addEventListener 'fetch', (e) -> | |
| e.respondWith main e | |
| main = (e) -> | |
| x = e.request.url.split '/' | |
| level = parseInt x[x.length-1] | |
| if x[x.length-2] isnt secret | |
| await notify_important "cfmonitor of #{x[x.length-2]} finished as secret mismatch" | |
| return new Response "finished", status: 200 | |
| res = do -> try | |
| await handleRequest e.request | |
| new Response "continue to next", status: 200 | |
| catch e | |
| new Response 'request failed', status: 500 | |
| e.waitUntil do -> try # waitUntil prevent the auto termination when respond finished (`res` resolves) | |
| await Promise.all [res, timeout 2000] # wait at least 2 seconds | |
| url = new URL(e.request.url) | |
| host = switch url.hostname | |
| when host1 then host2 | |
| when host2 then host1 | |
| else throw "from unknown host #{url.hostname}" | |
| next = await fetch new Request "https://#{host}/#{secret}/#{level+1}", | |
| method: 'POST' | |
| headers: 'Content-Type': 'application/json' | |
| body: JSON.stringify monitors | |
| if !next.ok | |
| throw "#{level+1}: returns status code #{next.status}" | |
| catch err | |
| await notify_important "cfmonitor fail on continue: #{do err.toString}" | |
| await res | |
| handleRequest = (req) -> | |
| if req.method is 'POST' | |
| for k, v of await do req.json | |
| Object.assign monitors[k], v | |
| updates = for k, v of monitors | |
| do v.update | |
| await Promise.all updates | |
| # notify_primary 'current status' + JSON.stringify monitors | |
| notify_telegram = (msg) -> | |
| res = await fetch new Request "https://api.telegram.org/bot#{telegram_token}/sendMessage", | |
| method: 'POST' | |
| headers: | |
| 'Accept': 'application/json' | |
| 'Content-Type': 'application/json' | |
| body: JSON.stringify chat_id: telegram_chatid, text: msg | |
| await do res.json | |
| notify_serverchan = (msg) -> | |
| fetch new Request "https://sc.ftqq.com/#{serverchan_token}.send?text=#{encodeURIComponent(msg)}", | |
| notify_primary = notify_telegram | |
| notify_important = (msg) -> | |
| Promise.all [ | |
| notify_serverchan msg | |
| notify_telegram msg | |
| ] | |
| timeout = (time) -> | |
| new Promise (resolve, reject) -> setTimeout resolve, time | |
| ServerUp = (url) -> | |
| last: null | |
| update: -> | |
| try | |
| x = await fetch new Request url | |
| throw '' if not x.ok | |
| if @last is false | |
| await notify_primary 'server is up' | |
| @last = true | |
| catch | |
| if @last is true | |
| await notify_primary 'server is down' | |
| @last = false | |
| monitors = | |
| github: ServerUp 'http://www.github.com' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment