1
0

wrappers.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. package main
  2. /*
  3. Wrappers.go
  4. This script provide wrapping functions
  5. for modules that do not provide
  6. handler interface within the modules
  7. --- NOTES ---
  8. If your module have more than one layer
  9. or require state keeping, please move
  10. the abstraction up one layer into
  11. your own module. Do not keep state on
  12. the global scope other than single
  13. Manager instance
  14. */
  15. import (
  16. "encoding/json"
  17. "fmt"
  18. "net/http"
  19. "strings"
  20. "time"
  21. "imuslab.com/zoraxy/mod/dynamicproxy"
  22. "imuslab.com/zoraxy/mod/ipscan"
  23. "imuslab.com/zoraxy/mod/mdns"
  24. "imuslab.com/zoraxy/mod/uptime"
  25. "imuslab.com/zoraxy/mod/utils"
  26. "imuslab.com/zoraxy/mod/wakeonlan"
  27. )
  28. /*
  29. Proxy Utils
  30. */
  31. //Check if site support TLS
  32. func HandleCheckSiteSupportTLS(w http.ResponseWriter, r *http.Request) {
  33. targetURL, err := utils.PostPara(r, "url")
  34. if err != nil {
  35. utils.SendErrorResponse(w, "invalid url given")
  36. return
  37. }
  38. httpsUrl := fmt.Sprintf("https://%s", targetURL)
  39. httpUrl := fmt.Sprintf("http://%s", targetURL)
  40. client := http.Client{Timeout: 5 * time.Second}
  41. resp, err := client.Head(httpsUrl)
  42. if err == nil && resp.StatusCode == http.StatusOK {
  43. js, _ := json.Marshal("https")
  44. utils.SendJSONResponse(w, string(js))
  45. return
  46. }
  47. resp, err = client.Head(httpUrl)
  48. if err == nil && resp.StatusCode == http.StatusOK {
  49. js, _ := json.Marshal("http")
  50. utils.SendJSONResponse(w, string(js))
  51. return
  52. }
  53. utils.SendErrorResponse(w, "invalid url given")
  54. }
  55. /*
  56. Statistic Summary
  57. */
  58. // Handle conversion of statistic daily summary to country summary
  59. func HandleCountryDistrSummary(w http.ResponseWriter, r *http.Request) {
  60. requestClientCountry := map[string]int{}
  61. statisticCollector.DailySummary.RequestClientIp.Range(func(key, value interface{}) bool {
  62. //Get this client country of original
  63. clientIp := key.(string)
  64. //requestCount := value.(int)
  65. ci, err := geodbStore.ResolveCountryCodeFromIP(clientIp)
  66. if err != nil {
  67. return true
  68. }
  69. isoCode := ci.CountryIsoCode
  70. if isoCode == "" {
  71. //local or reserved addr
  72. isoCode = "local"
  73. }
  74. uc, ok := requestClientCountry[isoCode]
  75. if !ok {
  76. //Create the counter
  77. requestClientCountry[isoCode] = 1
  78. } else {
  79. requestClientCountry[isoCode] = uc + 1
  80. }
  81. return true
  82. })
  83. js, _ := json.Marshal(requestClientCountry)
  84. utils.SendJSONResponse(w, string(js))
  85. }
  86. /*
  87. Up Time Monitor
  88. */
  89. // Update uptime monitor targets after rules updated
  90. // See https://github.com/tobychui/zoraxy/issues/77
  91. func UpdateUptimeMonitorTargets() {
  92. if uptimeMonitor != nil {
  93. uptimeMonitor.Config.Targets = GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter)
  94. go func() {
  95. uptimeMonitor.ExecuteUptimeCheck()
  96. }()
  97. SystemWideLogger.PrintAndLog("Uptime", "Uptime monitor config updated", nil)
  98. }
  99. }
  100. // Generate uptime monitor targets from reverse proxy rules
  101. func GetUptimeTargetsFromReverseProxyRules(dp *dynamicproxy.Router) []*uptime.Target {
  102. hosts := dp.GetProxyEndpointsAsMap()
  103. UptimeTargets := []*uptime.Target{}
  104. for subd, target := range hosts {
  105. url := "http://" + target.Domain
  106. protocol := "http"
  107. if target.RequireTLS {
  108. url = "https://" + target.Domain
  109. protocol = "https"
  110. }
  111. UptimeTargets = append(UptimeTargets, &uptime.Target{
  112. ID: subd,
  113. Name: subd,
  114. URL: url,
  115. Protocol: protocol,
  116. })
  117. }
  118. return UptimeTargets
  119. }
  120. // Handle rendering up time monitor data
  121. func HandleUptimeMonitorListing(w http.ResponseWriter, r *http.Request) {
  122. if uptimeMonitor != nil {
  123. uptimeMonitor.HandleUptimeLogRead(w, r)
  124. } else {
  125. http.Error(w, "500 - Internal Server Error", http.StatusInternalServerError)
  126. return
  127. }
  128. }
  129. // Handle listing current registered mdns nodes
  130. func HandleMdnsListing(w http.ResponseWriter, r *http.Request) {
  131. if mdnsScanner == nil {
  132. utils.SendErrorResponse(w, "mDNS scanner is disabled on this host")
  133. return
  134. }
  135. js, _ := json.Marshal(previousmdnsScanResults)
  136. utils.SendJSONResponse(w, string(js))
  137. }
  138. func HandleMdnsScanning(w http.ResponseWriter, r *http.Request) {
  139. if mdnsScanner == nil {
  140. utils.SendErrorResponse(w, "mDNS scanner is disabled on this host")
  141. return
  142. }
  143. domain, err := utils.PostPara(r, "domain")
  144. var hosts []*mdns.NetworkHost
  145. if err != nil {
  146. //Search for arozos node
  147. hosts = mdnsScanner.Scan(30, "")
  148. previousmdnsScanResults = hosts
  149. } else {
  150. //Search for other nodes
  151. hosts = mdnsScanner.Scan(30, domain)
  152. }
  153. js, _ := json.Marshal(hosts)
  154. utils.SendJSONResponse(w, string(js))
  155. }
  156. // handle ip scanning
  157. func HandleIpScan(w http.ResponseWriter, r *http.Request) {
  158. cidr, err := utils.PostPara(r, "cidr")
  159. if err != nil {
  160. //Ip range mode
  161. start, err := utils.PostPara(r, "start")
  162. if err != nil {
  163. utils.SendErrorResponse(w, "missing start ip")
  164. return
  165. }
  166. end, err := utils.PostPara(r, "end")
  167. if err != nil {
  168. utils.SendErrorResponse(w, "missing end ip")
  169. return
  170. }
  171. discoveredHosts, err := ipscan.ScanIpRange(start, end)
  172. if err != nil {
  173. utils.SendErrorResponse(w, err.Error())
  174. return
  175. }
  176. js, _ := json.Marshal(discoveredHosts)
  177. utils.SendJSONResponse(w, string(js))
  178. } else {
  179. //CIDR mode
  180. discoveredHosts, err := ipscan.ScanCIDRRange(cidr)
  181. if err != nil {
  182. utils.SendErrorResponse(w, err.Error())
  183. return
  184. }
  185. js, _ := json.Marshal(discoveredHosts)
  186. utils.SendJSONResponse(w, string(js))
  187. }
  188. }
  189. /*
  190. WAKE ON LAN
  191. Handle wake on LAN
  192. Support following methods
  193. /?set=xxx&name=xxx Record a new MAC address into the database
  194. /?wake=xxx Wake a server given its MAC address
  195. /?del=xxx Delete a server given its MAC address
  196. / Default: list all recorded WoL MAC address
  197. */
  198. func HandleWakeOnLan(w http.ResponseWriter, r *http.Request) {
  199. set, _ := utils.PostPara(r, "set")
  200. del, _ := utils.PostPara(r, "del")
  201. wake, _ := utils.PostPara(r, "wake")
  202. if set != "" {
  203. //Get the name of the describing server
  204. servername, err := utils.PostPara(r, "name")
  205. if err != nil {
  206. utils.SendErrorResponse(w, "invalid server name given")
  207. return
  208. }
  209. //Check if the given mac address is a valid mac address
  210. set = strings.TrimSpace(set)
  211. if !wakeonlan.IsValidMacAddress(set) {
  212. utils.SendErrorResponse(w, "invalid mac address given")
  213. return
  214. }
  215. //Store this into the database
  216. sysdb.Write("wolmac", set, servername)
  217. utils.SendOK(w)
  218. } else if wake != "" {
  219. //Wake the target up by MAC address
  220. if !wakeonlan.IsValidMacAddress(wake) {
  221. utils.SendErrorResponse(w, "invalid mac address given")
  222. return
  223. }
  224. SystemWideLogger.PrintAndLog("WoL", "Sending Wake on LAN magic packet to "+wake, nil)
  225. err := wakeonlan.WakeTarget(wake)
  226. if err != nil {
  227. utils.SendErrorResponse(w, err.Error())
  228. return
  229. }
  230. utils.SendOK(w)
  231. } else if del != "" {
  232. if !wakeonlan.IsValidMacAddress(del) {
  233. utils.SendErrorResponse(w, "invalid mac address given")
  234. return
  235. }
  236. sysdb.Delete("wolmac", del)
  237. utils.SendOK(w)
  238. } else {
  239. //List all the saved WoL MAC Address
  240. entries, err := sysdb.ListTable("wolmac")
  241. if err != nil {
  242. utils.SendErrorResponse(w, "unknown error occured")
  243. return
  244. }
  245. type MacAddrRecord struct {
  246. ServerName string
  247. MacAddr string
  248. }
  249. results := []*MacAddrRecord{}
  250. for _, keypairs := range entries {
  251. macAddr := string(keypairs[0])
  252. serverName := ""
  253. json.Unmarshal(keypairs[1], &serverName)
  254. results = append(results, &MacAddrRecord{
  255. ServerName: serverName,
  256. MacAddr: macAddr,
  257. })
  258. }
  259. js, _ := json.Marshal(results)
  260. utils.SendJSONResponse(w, string(js))
  261. }
  262. }
  263. /*
  264. Zoraxy Host Info
  265. */
  266. func HandleZoraxyInfo(w http.ResponseWriter, r *http.Request) {
  267. type ZoraxyInfo struct {
  268. Version string
  269. NodeUUID string
  270. Development bool
  271. BootTime int64
  272. EnableSshLoopback bool
  273. ZerotierConnected bool
  274. }
  275. info := ZoraxyInfo{
  276. Version: version,
  277. NodeUUID: nodeUUID,
  278. Development: development,
  279. BootTime: bootTime,
  280. EnableSshLoopback: *allowSshLoopback,
  281. ZerotierConnected: ganManager.ControllerID != "",
  282. }
  283. js, _ := json.MarshalIndent(info, "", " ")
  284. utils.SendJSONResponse(w, string(js))
  285. }
  286. func HandleGeoIpLookup(w http.ResponseWriter, r *http.Request) {
  287. ip, err := utils.GetPara(r, "ip")
  288. if err != nil {
  289. utils.SendErrorResponse(w, "ip not given")
  290. return
  291. }
  292. cc, err := geodbStore.ResolveCountryCodeFromIP(ip)
  293. if err != nil {
  294. utils.SendErrorResponse(w, err.Error())
  295. return
  296. }
  297. js, _ := json.Marshal(cc)
  298. utils.SendJSONResponse(w, string(js))
  299. }