wrappers.go 7.8 KB

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