123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- package main
- /*
- Wrappers.go
- This script provide wrapping functions
- for modules that do not provide
- handler interface within the modules
- --- NOTES ---
- If your module have more than one layer
- or require state keeping, please move
- the abstraction up one layer into
- your own module. Do not keep state on
- the global scope other than single
- Manager instance
- */
- import (
- "encoding/json"
- "net/http"
- "strconv"
- "strings"
- "imuslab.com/zoraxy/mod/dynamicproxy"
- "imuslab.com/zoraxy/mod/dynamicproxy/loadbalance"
- "imuslab.com/zoraxy/mod/mdns"
- "imuslab.com/zoraxy/mod/uptime"
- "imuslab.com/zoraxy/mod/utils"
- "imuslab.com/zoraxy/mod/wakeonlan"
- )
- /*
- Statistic Summary
- */
- // Handle conversion of statistic daily summary to country summary
- func HandleCountryDistrSummary(w http.ResponseWriter, r *http.Request) {
- requestClientCountry := map[string]int{}
- statisticCollector.DailySummary.RequestClientIp.Range(func(key, value interface{}) bool {
- //Get this client country of original
- clientIp := key.(string)
- //requestCount := value.(int)
- ci, err := geodbStore.ResolveCountryCodeFromIP(clientIp)
- if err != nil {
- return true
- }
- isoCode := ci.CountryIsoCode
- if isoCode == "" {
- //local or reserved addr
- isoCode = "local"
- }
- uc, ok := requestClientCountry[isoCode]
- if !ok {
- //Create the counter
- requestClientCountry[isoCode] = 1
- } else {
- requestClientCountry[isoCode] = uc + 1
- }
- return true
- })
- js, _ := json.Marshal(requestClientCountry)
- utils.SendJSONResponse(w, string(js))
- }
- /*
- Up Time Monitor
- */
- // Update uptime monitor targets after rules updated
- // See https://github.com/tobychui/zoraxy/issues/77
- func UpdateUptimeMonitorTargets() {
- if uptimeMonitor != nil {
- uptimeMonitor.Config.Targets = GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter)
- uptimeMonitor.CleanRecords()
- go func() {
- uptimeMonitor.ExecuteUptimeCheck()
- }()
- SystemWideLogger.PrintAndLog("uptime-monitor", "Uptime monitor config updated", nil)
- }
- }
- // Generate uptime monitor targets from reverse proxy rules
- func GetUptimeTargetsFromReverseProxyRules(dp *dynamicproxy.Router) []*uptime.Target {
- hosts := dp.GetProxyEndpointsAsMap()
- UptimeTargets := []*uptime.Target{}
- for hostid, target := range hosts {
- if target.Disabled || target.DisableUptimeMonitor {
- //Skip those proxy rules that is disabled
- continue
- }
- isMultipleUpstreams := len(target.ActiveOrigins) > 1
- for i, origin := range target.ActiveOrigins {
- url := "http://" + origin.OriginIpOrDomain
- protocol := "http"
- if origin.RequireTLS {
- url = "https://" + origin.OriginIpOrDomain
- protocol = "https"
- }
- //Add the root url
- hostIdAndName := hostid
- if isMultipleUpstreams {
- hostIdAndName = hostIdAndName + " (upstream:" + strconv.Itoa(i) + ")"
- }
- UptimeTargets = append(UptimeTargets, &uptime.Target{
- ID: hostIdAndName,
- Name: hostIdAndName,
- URL: url,
- Protocol: protocol,
- ProxyType: uptime.ProxyType_Host,
- })
- //Add each virtual directory into the list
- for _, vdir := range target.VirtualDirectories {
- url := "http://" + vdir.Domain
- protocol := "http"
- if origin.RequireTLS {
- url = "https://" + vdir.Domain
- protocol = "https"
- }
- //Add the root url
- UptimeTargets = append(UptimeTargets, &uptime.Target{
- ID: hostid + vdir.MatchingPath,
- Name: hostid + vdir.MatchingPath,
- URL: url,
- Protocol: protocol,
- ProxyType: uptime.ProxyType_Vdir,
- })
- }
- }
- }
- return UptimeTargets
- }
- // Handle rendering up time monitor data
- func HandleUptimeMonitorListing(w http.ResponseWriter, r *http.Request) {
- if uptimeMonitor != nil {
- uptimeMonitor.HandleUptimeLogRead(w, r)
- } else {
- http.Error(w, "500 - Internal Server Error", http.StatusInternalServerError)
- return
- }
- }
- /*
- Static Web Server
- */
- // Handle port change, if root router is using internal static web server
- // update the root router as well
- func HandleStaticWebServerPortChange(w http.ResponseWriter, r *http.Request) {
- newPort, err := utils.PostInt(r, "port")
- if err != nil {
- utils.SendErrorResponse(w, "invalid port number given")
- return
- }
- if dynamicProxyRouter.Root.DefaultSiteOption == dynamicproxy.DefaultSite_InternalStaticWebServer {
- //Update the root site as well
- newDraftingRoot := dynamicProxyRouter.Root.Clone()
- newDraftingRoot.ActiveOrigins = []*loadbalance.Upstream{
- {
- OriginIpOrDomain: "127.0.0.1:" + strconv.Itoa(newPort),
- RequireTLS: false,
- SkipCertValidations: false,
- SkipWebSocketOriginCheck: true,
- Weight: 0,
- },
- }
- activatedNewRoot, err := dynamicProxyRouter.PrepareProxyRoute(newDraftingRoot)
- if err != nil {
- utils.SendErrorResponse(w, "unable to update root routing rule")
- return
- }
- //Replace the root
- dynamicProxyRouter.Root = activatedNewRoot
- SaveReverseProxyConfig(newDraftingRoot)
- }
- err = staticWebServer.ChangePort(strconv.Itoa(newPort))
- if err != nil {
- utils.SendErrorResponse(w, err.Error())
- return
- }
- utils.SendOK(w)
- }
- /*
- mDNS Scanning
- */
- // Handle listing current registered mdns nodes
- func HandleMdnsListing(w http.ResponseWriter, r *http.Request) {
- if mdnsScanner == nil {
- utils.SendErrorResponse(w, "mDNS scanner is disabled on this host")
- return
- }
- js, _ := json.Marshal(previousmdnsScanResults)
- utils.SendJSONResponse(w, string(js))
- }
- func HandleMdnsScanning(w http.ResponseWriter, r *http.Request) {
- if mdnsScanner == nil {
- utils.SendErrorResponse(w, "mDNS scanner is disabled on this host")
- return
- }
- domain, err := utils.PostPara(r, "domain")
- var hosts []*mdns.NetworkHost
- if err != nil {
- //Search for arozos node
- hosts = mdnsScanner.Scan(30, "")
- previousmdnsScanResults = hosts
- } else {
- //Search for other nodes
- hosts = mdnsScanner.Scan(30, domain)
- }
- js, _ := json.Marshal(hosts)
- utils.SendJSONResponse(w, string(js))
- }
- /*
- WAKE ON LAN
- Handle wake on LAN
- Support following methods
- /?set=xxx&name=xxx Record a new MAC address into the database
- /?wake=xxx Wake a server given its MAC address
- /?del=xxx Delete a server given its MAC address
- / Default: list all recorded WoL MAC address
- */
- func HandleWakeOnLan(w http.ResponseWriter, r *http.Request) {
- set, _ := utils.PostPara(r, "set")
- del, _ := utils.PostPara(r, "del")
- wake, _ := utils.PostPara(r, "wake")
- if set != "" {
- //Get the name of the describing server
- servername, err := utils.PostPara(r, "name")
- if err != nil {
- utils.SendErrorResponse(w, "invalid server name given")
- return
- }
- //Check if the given mac address is a valid mac address
- set = strings.TrimSpace(set)
- if !wakeonlan.IsValidMacAddress(set) {
- utils.SendErrorResponse(w, "invalid mac address given")
- return
- }
- //Store this into the database
- sysdb.Write("wolmac", set, servername)
- utils.SendOK(w)
- } else if wake != "" {
- //Wake the target up by MAC address
- if !wakeonlan.IsValidMacAddress(wake) {
- utils.SendErrorResponse(w, "invalid mac address given")
- return
- }
- SystemWideLogger.PrintAndLog("WoL", "Sending Wake on LAN magic packet to "+wake, nil)
- err := wakeonlan.WakeTarget(wake)
- if err != nil {
- utils.SendErrorResponse(w, err.Error())
- return
- }
- utils.SendOK(w)
- } else if del != "" {
- if !wakeonlan.IsValidMacAddress(del) {
- utils.SendErrorResponse(w, "invalid mac address given")
- return
- }
- sysdb.Delete("wolmac", del)
- utils.SendOK(w)
- } else {
- //List all the saved WoL MAC Address
- entries, err := sysdb.ListTable("wolmac")
- if err != nil {
- utils.SendErrorResponse(w, "unknown error occured")
- return
- }
- type MacAddrRecord struct {
- ServerName string
- MacAddr string
- }
- results := []*MacAddrRecord{}
- for _, keypairs := range entries {
- macAddr := string(keypairs[0])
- serverName := ""
- json.Unmarshal(keypairs[1], &serverName)
- results = append(results, &MacAddrRecord{
- ServerName: serverName,
- MacAddr: macAddr,
- })
- }
- js, _ := json.Marshal(results)
- utils.SendJSONResponse(w, string(js))
- }
- }
- /*
- Zoraxy Host Info
- */
- func HandleZoraxyInfo(w http.ResponseWriter, r *http.Request) {
- type ZoraxyInfo struct {
- Version string
- NodeUUID string
- Development bool
- BootTime int64
- EnableSshLoopback bool
- ZerotierConnected bool
- }
- displayUUID := nodeUUID
- displayAllowSSHLB := *allowSshLoopback
- displayBootTime := bootTime
- if !authAgent.CheckAuth(r) {
- displayUUID = "Unauthorized"
- displayAllowSSHLB = false
- displayBootTime = 0
- }
- info := ZoraxyInfo{
- Version: SYSTEM_VERSION,
- NodeUUID: displayUUID,
- Development: DEVELOPMENT_BUILD,
- BootTime: displayBootTime,
- EnableSshLoopback: displayAllowSSHLB,
- ZerotierConnected: ganManager.ControllerID != "",
- }
- js, _ := json.MarshalIndent(info, "", " ")
- utils.SendJSONResponse(w, string(js))
- }
- func HandleGeoIpLookup(w http.ResponseWriter, r *http.Request) {
- ip, err := utils.GetPara(r, "ip")
- if err != nil {
- utils.SendErrorResponse(w, "ip not given")
- return
- }
- cc, err := geodbStore.ResolveCountryCodeFromIP(ip)
- if err != nil {
- utils.SendErrorResponse(w, err.Error())
- return
- }
- js, _ := json.Marshal(cc)
- utils.SendJSONResponse(w, string(js))
- }
|