mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-06 07:37:21 +02:00
Refactorized main entry function
- Moved constants to def.go - Added acme close function (not used for now) - Added robots.txt to prevent webmin panel being scanned by search engine
This commit is contained in:
parent
293a527ffc
commit
c5170bcb94
20
src/acme.go
20
src/acme.go
@ -41,6 +41,20 @@ func initACME() *acme.ACMEHandler {
|
|||||||
return acme.NewACME("https://acme-v02.api.letsencrypt.org/directory", strconv.Itoa(port), sysdb, SystemWideLogger)
|
return acme.NewACME("https://acme-v02.api.letsencrypt.org/directory", strconv.Itoa(port), sysdb, SystemWideLogger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restart ACME handler and auto renewer
|
||||||
|
func restartACMEHandler() {
|
||||||
|
SystemWideLogger.Println("Restarting ACME handler")
|
||||||
|
//Clos the current handler and auto renewer
|
||||||
|
acmeHandler.Close()
|
||||||
|
acmeAutoRenewer.Close()
|
||||||
|
acmeDeregisterSpecialRoutingRule()
|
||||||
|
|
||||||
|
//Reinit the handler with a new random port
|
||||||
|
acmeHandler = initACME()
|
||||||
|
|
||||||
|
acmeRegisterSpecialRoutingRule()
|
||||||
|
}
|
||||||
|
|
||||||
// create the special routing rule for ACME
|
// create the special routing rule for ACME
|
||||||
func acmeRegisterSpecialRoutingRule() {
|
func acmeRegisterSpecialRoutingRule() {
|
||||||
SystemWideLogger.Println("Assigned temporary port:" + acmeHandler.Getport())
|
SystemWideLogger.Println("Assigned temporary port:" + acmeHandler.Getport())
|
||||||
@ -82,6 +96,12 @@ func acmeRegisterSpecialRoutingRule() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove the special routing rule for ACME
|
||||||
|
func acmeDeregisterSpecialRoutingRule() {
|
||||||
|
SystemWideLogger.Println("Removing ACME routing rule")
|
||||||
|
dynamicProxyRouter.RemoveRoutingRule("acme-autorenew")
|
||||||
|
}
|
||||||
|
|
||||||
// This function check if the renew setup is satisfied. If not, toggle them automatically
|
// This function check if the renew setup is satisfied. If not, toggle them automatically
|
||||||
func AcmeCheckAndHandleRenewCertificate(w http.ResponseWriter, r *http.Request) {
|
func AcmeCheckAndHandleRenewCertificate(w http.ResponseWriter, r *http.Request) {
|
||||||
isForceHttpsRedirectEnabledOriginally := false
|
isForceHttpsRedirectEnabledOriginally := false
|
||||||
|
@ -21,8 +21,7 @@ import (
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var requireAuth = true
|
/* Register all the APIs */
|
||||||
|
|
||||||
func initAPIs(targetMux *http.ServeMux) {
|
func initAPIs(targetMux *http.ServeMux) {
|
||||||
authRouter := auth.NewManagedHTTPRouter(auth.RouterOption{
|
authRouter := auth.NewManagedHTTPRouter(auth.RouterOption{
|
||||||
AuthAgent: authAgent,
|
AuthAgent: authAgent,
|
||||||
@ -35,7 +34,7 @@ func initAPIs(targetMux *http.ServeMux) {
|
|||||||
|
|
||||||
//Register the standard web services urls
|
//Register the standard web services urls
|
||||||
fs := http.FileServer(http.FS(webres))
|
fs := http.FileServer(http.FS(webres))
|
||||||
if development {
|
if DEVELOPMENT_BUILD {
|
||||||
fs = http.FileServer(http.Dir("web/"))
|
fs = http.FileServer(http.Dir("web/"))
|
||||||
}
|
}
|
||||||
//Add a layer of middleware for advance control
|
//Add a layer of middleware for advance control
|
||||||
@ -215,7 +214,7 @@ func initAPIs(targetMux *http.ServeMux) {
|
|||||||
authRouter.HandleFunc("/api/acme/autoRenew/email", acmeAutoRenewer.HandleACMEEmail)
|
authRouter.HandleFunc("/api/acme/autoRenew/email", acmeAutoRenewer.HandleACMEEmail)
|
||||||
authRouter.HandleFunc("/api/acme/autoRenew/setDomains", acmeAutoRenewer.HandleSetAutoRenewDomains)
|
authRouter.HandleFunc("/api/acme/autoRenew/setDomains", acmeAutoRenewer.HandleSetAutoRenewDomains)
|
||||||
authRouter.HandleFunc("/api/acme/autoRenew/setEAB", acmeAutoRenewer.HanldeSetEAB)
|
authRouter.HandleFunc("/api/acme/autoRenew/setEAB", acmeAutoRenewer.HanldeSetEAB)
|
||||||
authRouter.HandleFunc("/api/acme/autoRenew/setDNS", acmeAutoRenewer.HanldeSetDNS)
|
authRouter.HandleFunc("/api/acme/autoRenew/setDNS", acmeAutoRenewer.HandleSetDNS)
|
||||||
authRouter.HandleFunc("/api/acme/autoRenew/listDomains", acmeAutoRenewer.HandleLoadAutoRenewDomains)
|
authRouter.HandleFunc("/api/acme/autoRenew/listDomains", acmeAutoRenewer.HandleLoadAutoRenewDomains)
|
||||||
authRouter.HandleFunc("/api/acme/autoRenew/renewPolicy", acmeAutoRenewer.HandleRenewPolicy)
|
authRouter.HandleFunc("/api/acme/autoRenew/renewPolicy", acmeAutoRenewer.HandleRenewPolicy)
|
||||||
authRouter.HandleFunc("/api/acme/autoRenew/renewNow", acmeAutoRenewer.HandleRenewNow)
|
authRouter.HandleFunc("/api/acme/autoRenew/renewNow", acmeAutoRenewer.HandleRenewNow)
|
||||||
|
135
src/def.go
Normal file
135
src/def.go
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
Type and flag definations
|
||||||
|
|
||||||
|
This file contains all the type and flag definations
|
||||||
|
Author: tobychui
|
||||||
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"flag"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/access"
|
||||||
|
"imuslab.com/zoraxy/mod/acme"
|
||||||
|
"imuslab.com/zoraxy/mod/auth"
|
||||||
|
"imuslab.com/zoraxy/mod/auth/sso"
|
||||||
|
"imuslab.com/zoraxy/mod/database"
|
||||||
|
"imuslab.com/zoraxy/mod/dockerux"
|
||||||
|
"imuslab.com/zoraxy/mod/dynamicproxy/loadbalance"
|
||||||
|
"imuslab.com/zoraxy/mod/dynamicproxy/redirection"
|
||||||
|
"imuslab.com/zoraxy/mod/email"
|
||||||
|
"imuslab.com/zoraxy/mod/forwardproxy"
|
||||||
|
"imuslab.com/zoraxy/mod/ganserv"
|
||||||
|
"imuslab.com/zoraxy/mod/geodb"
|
||||||
|
"imuslab.com/zoraxy/mod/info/logger"
|
||||||
|
"imuslab.com/zoraxy/mod/info/logviewer"
|
||||||
|
"imuslab.com/zoraxy/mod/mdns"
|
||||||
|
"imuslab.com/zoraxy/mod/netstat"
|
||||||
|
"imuslab.com/zoraxy/mod/pathrule"
|
||||||
|
"imuslab.com/zoraxy/mod/sshprox"
|
||||||
|
"imuslab.com/zoraxy/mod/statistic"
|
||||||
|
"imuslab.com/zoraxy/mod/statistic/analytic"
|
||||||
|
"imuslab.com/zoraxy/mod/streamproxy"
|
||||||
|
"imuslab.com/zoraxy/mod/tlscert"
|
||||||
|
"imuslab.com/zoraxy/mod/uptime"
|
||||||
|
"imuslab.com/zoraxy/mod/webserv"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
/* Build Constants */
|
||||||
|
SYSTEM_NAME = "Zoraxy"
|
||||||
|
SYSTEM_VERSION = "3.1.4"
|
||||||
|
DEVELOPMENT_BUILD = true /* Development: Set to false to use embedded web fs */
|
||||||
|
|
||||||
|
/* System Constants */
|
||||||
|
DATABASE_PATH = "sys.db"
|
||||||
|
TMP_FOLDER = "./tmp"
|
||||||
|
WEBSERV_DEFAULT_PORT = 5487
|
||||||
|
MDNS_HOSTNAME_PREFIX = "zoraxy_" /* Follow by node UUID */
|
||||||
|
MDNS_IDENTIFY_DEVICE_TYPE = "Network Gateway"
|
||||||
|
MDNS_IDENTIFY_DOMAIN = "zoraxy.aroz.org"
|
||||||
|
MDNS_IDENTIFY_VENDOR = "imuslab.com"
|
||||||
|
MDNS_SCAN_TIMEOUT = 30 /* Seconds */
|
||||||
|
MDNS_SCAN_UPDATE_INTERVAL = 15 /* Minutes */
|
||||||
|
ACME_AUTORENEW_CONFIG_PATH = "./conf/acme_conf.json"
|
||||||
|
CSRF_COOKIENAME = "zoraxy_csrf"
|
||||||
|
LOG_PREFIX = "zr"
|
||||||
|
LOG_FOLDER = "./log"
|
||||||
|
LOG_EXTENSION = ".log"
|
||||||
|
|
||||||
|
/* Configuration Folder Storage Path Constants */
|
||||||
|
CONF_HTTP_PROXY = "./conf/proxy"
|
||||||
|
CONF_STREAM_PROXY = "./conf/streamproxy"
|
||||||
|
CONF_CERT_STORE = "./conf/certs"
|
||||||
|
CONF_REDIRECTION = "./conf/redirect"
|
||||||
|
CONF_ACCESS_RULE = "./conf/access"
|
||||||
|
CONF_PATH_RULE = "./conf/rules/pathrules"
|
||||||
|
)
|
||||||
|
|
||||||
|
/* System Startup Flags */
|
||||||
|
var webUIPort = flag.String("port", ":8000", "Management web interface listening port")
|
||||||
|
var noauth = flag.Bool("noauth", false, "Disable authentication for management interface")
|
||||||
|
var showver = flag.Bool("version", false, "Show version of this server")
|
||||||
|
var allowSshLoopback = flag.Bool("sshlb", false, "Allow loopback web ssh connection (DANGER)")
|
||||||
|
var allowMdnsScanning = flag.Bool("mdns", true, "Enable mDNS scanner and transponder")
|
||||||
|
var mdnsName = flag.String("mdnsname", "", "mDNS name, leave empty to use default (zoraxy_{node-uuid}.local)")
|
||||||
|
var ztAuthToken = flag.String("ztauth", "", "ZeroTier authtoken for the local node")
|
||||||
|
var ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port")
|
||||||
|
var runningInDocker = flag.Bool("docker", false, "Run Zoraxy in docker compatibility mode")
|
||||||
|
var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)")
|
||||||
|
var acmeCertAutoRenewDays = flag.Int("earlyrenew", 30, "Number of days to early renew a soon expiring certificate (days)")
|
||||||
|
var enableHighSpeedGeoIPLookup = flag.Bool("fastgeoip", false, "Enable high speed geoip lookup, require 1GB extra memory (Not recommend for low end devices)")
|
||||||
|
var staticWebServerRoot = flag.String("webroot", "./www", "Static web server root folder. Only allow chnage in start paramters")
|
||||||
|
var allowWebFileManager = flag.Bool("webfm", true, "Enable web file manager for static web server root folder")
|
||||||
|
var enableAutoUpdate = flag.Bool("cfgupgrade", true, "Enable auto config upgrade if breaking change is detected")
|
||||||
|
|
||||||
|
/* Global Variables and Handlers */
|
||||||
|
var (
|
||||||
|
nodeUUID = "generic" //System uuid, in uuidv4 format, load from database on startup
|
||||||
|
bootTime = time.Now().Unix()
|
||||||
|
requireAuth = true /* Require authentication for webmin panel */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Binary Embedding File System
|
||||||
|
*/
|
||||||
|
//go:embed web/*
|
||||||
|
webres embed.FS
|
||||||
|
|
||||||
|
/*
|
||||||
|
Handler Modules
|
||||||
|
*/
|
||||||
|
sysdb *database.Database //System database
|
||||||
|
authAgent *auth.AuthAgent //Authentication agent
|
||||||
|
tlsCertManager *tlscert.Manager //TLS / SSL management
|
||||||
|
redirectTable *redirection.RuleTable //Handle special redirection rule sets
|
||||||
|
webminPanelMux *http.ServeMux //Server mux for handling webmin panel APIs
|
||||||
|
csrfMiddleware func(http.Handler) http.Handler //CSRF protection middleware
|
||||||
|
|
||||||
|
pathRuleHandler *pathrule.Handler //Handle specific path blocking or custom headers
|
||||||
|
geodbStore *geodb.Store //GeoIP database, for resolving IP into country code
|
||||||
|
accessController *access.Controller //Access controller, handle black list and white list
|
||||||
|
netstatBuffers *netstat.NetStatBuffers //Realtime graph buffers
|
||||||
|
statisticCollector *statistic.Collector //Collecting statistic from visitors
|
||||||
|
uptimeMonitor *uptime.Monitor //Uptime monitor service worker
|
||||||
|
mdnsScanner *mdns.MDNSHost //mDNS discovery services
|
||||||
|
ganManager *ganserv.NetworkManager //Global Area Network Manager
|
||||||
|
webSshManager *sshprox.Manager //Web SSH connection service
|
||||||
|
streamProxyManager *streamproxy.Manager //Stream Proxy Manager for TCP / UDP forwarding
|
||||||
|
acmeHandler *acme.ACMEHandler //Handler for ACME Certificate renew
|
||||||
|
acmeAutoRenewer *acme.AutoRenewer //Handler for ACME auto renew ticking
|
||||||
|
staticWebServer *webserv.WebServer //Static web server for hosting simple stuffs
|
||||||
|
forwardProxy *forwardproxy.Handler //HTTP Forward proxy, basically VPN for web browser
|
||||||
|
loadBalancer *loadbalance.RouteManager //Global scope loadbalancer, store the state of the lb routing
|
||||||
|
ssoHandler *sso.SSOHandler //Single Sign On handler
|
||||||
|
|
||||||
|
//Helper modules
|
||||||
|
EmailSender *email.Sender //Email sender that handle email sending
|
||||||
|
AnalyticLoader *analytic.DataLoader //Data loader for Zoraxy Analytic
|
||||||
|
DockerUXOptimizer *dockerux.UXOptimizer //Docker user experience optimizer, community contribution only
|
||||||
|
SystemWideLogger *logger.Logger //Logger for Zoraxy
|
||||||
|
LogViewer *logviewer.Viewer
|
||||||
|
)
|
135
src/main.go
135
src/main.go
@ -1,7 +1,36 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
______
|
||||||
|
|___ /
|
||||||
|
/ / ___ _ __ __ ___ ___ _
|
||||||
|
/ / / _ \| '__/ _` \ \/ / | | |
|
||||||
|
/ /_| (_) | | | (_| |> <| |_| |
|
||||||
|
/_____\___/|_| \__,_/_/\_\\__, |
|
||||||
|
__/ |
|
||||||
|
|___/
|
||||||
|
|
||||||
|
Zoraxy - A general purpose HTTP reverse proxy and forwarding tool
|
||||||
|
Author: tobychui
|
||||||
|
License: AGPLv3
|
||||||
|
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, version 3 of the License or any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
@ -13,100 +42,11 @@ import (
|
|||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/gorilla/csrf"
|
"github.com/gorilla/csrf"
|
||||||
"imuslab.com/zoraxy/mod/access"
|
|
||||||
"imuslab.com/zoraxy/mod/acme"
|
|
||||||
"imuslab.com/zoraxy/mod/auth"
|
|
||||||
"imuslab.com/zoraxy/mod/auth/sso"
|
|
||||||
"imuslab.com/zoraxy/mod/database"
|
|
||||||
"imuslab.com/zoraxy/mod/dockerux"
|
|
||||||
"imuslab.com/zoraxy/mod/dynamicproxy/loadbalance"
|
|
||||||
"imuslab.com/zoraxy/mod/dynamicproxy/redirection"
|
|
||||||
"imuslab.com/zoraxy/mod/email"
|
|
||||||
"imuslab.com/zoraxy/mod/forwardproxy"
|
|
||||||
"imuslab.com/zoraxy/mod/ganserv"
|
|
||||||
"imuslab.com/zoraxy/mod/geodb"
|
|
||||||
"imuslab.com/zoraxy/mod/info/logger"
|
|
||||||
"imuslab.com/zoraxy/mod/info/logviewer"
|
|
||||||
"imuslab.com/zoraxy/mod/mdns"
|
|
||||||
"imuslab.com/zoraxy/mod/netstat"
|
|
||||||
"imuslab.com/zoraxy/mod/pathrule"
|
|
||||||
"imuslab.com/zoraxy/mod/sshprox"
|
|
||||||
"imuslab.com/zoraxy/mod/statistic"
|
|
||||||
"imuslab.com/zoraxy/mod/statistic/analytic"
|
|
||||||
"imuslab.com/zoraxy/mod/streamproxy"
|
|
||||||
"imuslab.com/zoraxy/mod/tlscert"
|
|
||||||
"imuslab.com/zoraxy/mod/update"
|
"imuslab.com/zoraxy/mod/update"
|
||||||
"imuslab.com/zoraxy/mod/uptime"
|
|
||||||
"imuslab.com/zoraxy/mod/utils"
|
"imuslab.com/zoraxy/mod/utils"
|
||||||
"imuslab.com/zoraxy/mod/webserv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// General flags
|
/* SIGTERM handler, do shutdown sequences before closing */
|
||||||
var webUIPort = flag.String("port", ":8000", "Management web interface listening port")
|
|
||||||
var noauth = flag.Bool("noauth", false, "Disable authentication for management interface")
|
|
||||||
var showver = flag.Bool("version", false, "Show version of this server")
|
|
||||||
var allowSshLoopback = flag.Bool("sshlb", false, "Allow loopback web ssh connection (DANGER)")
|
|
||||||
var allowMdnsScanning = flag.Bool("mdns", true, "Enable mDNS scanner and transponder")
|
|
||||||
var mdnsName = flag.String("mdnsname", "", "mDNS name, leave empty to use default (zoraxy_{node-uuid}.local)")
|
|
||||||
var ztAuthToken = flag.String("ztauth", "", "ZeroTier authtoken for the local node")
|
|
||||||
var ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port")
|
|
||||||
var runningInDocker = flag.Bool("docker", false, "Run Zoraxy in docker compatibility mode")
|
|
||||||
var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)")
|
|
||||||
var acmeCertAutoRenewDays = flag.Int("earlyrenew", 30, "Number of days to early renew a soon expiring certificate (days)")
|
|
||||||
var enableHighSpeedGeoIPLookup = flag.Bool("fastgeoip", false, "Enable high speed geoip lookup, require 1GB extra memory (Not recommend for low end devices)")
|
|
||||||
var staticWebServerRoot = flag.String("webroot", "./www", "Static web server root folder. Only allow chnage in start paramters")
|
|
||||||
var allowWebFileManager = flag.Bool("webfm", true, "Enable web file manager for static web server root folder")
|
|
||||||
var enableAutoUpdate = flag.Bool("cfgupgrade", true, "Enable auto config upgrade if breaking change is detected")
|
|
||||||
|
|
||||||
var (
|
|
||||||
name = "Zoraxy"
|
|
||||||
version = "3.1.4"
|
|
||||||
nodeUUID = "generic" //System uuid, in uuidv4 format
|
|
||||||
development = true //Set this to false to use embedded web fs
|
|
||||||
bootTime = time.Now().Unix()
|
|
||||||
|
|
||||||
/*
|
|
||||||
Binary Embedding File System
|
|
||||||
*/
|
|
||||||
//go:embed web/*
|
|
||||||
webres embed.FS
|
|
||||||
|
|
||||||
/*
|
|
||||||
Handler Modules
|
|
||||||
*/
|
|
||||||
sysdb *database.Database //System database
|
|
||||||
authAgent *auth.AuthAgent //Authentication agent
|
|
||||||
tlsCertManager *tlscert.Manager //TLS / SSL management
|
|
||||||
redirectTable *redirection.RuleTable //Handle special redirection rule sets
|
|
||||||
webminPanelMux *http.ServeMux //Server mux for handling webmin panel APIs
|
|
||||||
csrfMiddleware func(http.Handler) http.Handler //CSRF protection middleware
|
|
||||||
|
|
||||||
pathRuleHandler *pathrule.Handler //Handle specific path blocking or custom headers
|
|
||||||
geodbStore *geodb.Store //GeoIP database, for resolving IP into country code
|
|
||||||
accessController *access.Controller //Access controller, handle black list and white list
|
|
||||||
netstatBuffers *netstat.NetStatBuffers //Realtime graph buffers
|
|
||||||
statisticCollector *statistic.Collector //Collecting statistic from visitors
|
|
||||||
uptimeMonitor *uptime.Monitor //Uptime monitor service worker
|
|
||||||
mdnsScanner *mdns.MDNSHost //mDNS discovery services
|
|
||||||
ganManager *ganserv.NetworkManager //Global Area Network Manager
|
|
||||||
webSshManager *sshprox.Manager //Web SSH connection service
|
|
||||||
streamProxyManager *streamproxy.Manager //Stream Proxy Manager for TCP / UDP forwarding
|
|
||||||
acmeHandler *acme.ACMEHandler //Handler for ACME Certificate renew
|
|
||||||
acmeAutoRenewer *acme.AutoRenewer //Handler for ACME auto renew ticking
|
|
||||||
staticWebServer *webserv.WebServer //Static web server for hosting simple stuffs
|
|
||||||
forwardProxy *forwardproxy.Handler //HTTP Forward proxy, basically VPN for web browser
|
|
||||||
loadBalancer *loadbalance.RouteManager //Global scope loadbalancer, store the state of the lb routing
|
|
||||||
ssoHandler *sso.SSOHandler //Single Sign On handler
|
|
||||||
|
|
||||||
//Helper modules
|
|
||||||
EmailSender *email.Sender //Email sender that handle email sending
|
|
||||||
AnalyticLoader *analytic.DataLoader //Data loader for Zoraxy Analytic
|
|
||||||
DockerUXOptimizer *dockerux.UXOptimizer //Docker user experience optimizer, community contribution only
|
|
||||||
SystemWideLogger *logger.Logger //Logger for Zoraxy
|
|
||||||
LogViewer *logviewer.Viewer
|
|
||||||
)
|
|
||||||
|
|
||||||
// Kill signal handler. Do something before the system the core terminate.
|
|
||||||
func SetupCloseHandler() {
|
func SetupCloseHandler() {
|
||||||
c := make(chan os.Signal, 2)
|
c := make(chan os.Signal, 2)
|
||||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||||
@ -118,9 +58,7 @@ func SetupCloseHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ShutdownSeq() {
|
func ShutdownSeq() {
|
||||||
SystemWideLogger.Println("Shutting down " + name)
|
SystemWideLogger.Println("Shutting down " + SYSTEM_NAME)
|
||||||
//SystemWideLogger.Println("Closing GeoDB")
|
|
||||||
//geodbStore.Close()
|
|
||||||
SystemWideLogger.Println("Closing Netstats Listener")
|
SystemWideLogger.Println("Closing Netstats Listener")
|
||||||
netstatBuffers.Close()
|
netstatBuffers.Close()
|
||||||
SystemWideLogger.Println("Closing Statistic Collector")
|
SystemWideLogger.Println("Closing Statistic Collector")
|
||||||
@ -152,7 +90,7 @@ func main() {
|
|||||||
//Parse startup flags
|
//Parse startup flags
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if *showver {
|
if *showver {
|
||||||
fmt.Println(name + " - Version " + version)
|
fmt.Println(SYSTEM_NAME + " - Version " + SYSTEM_VERSION)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +101,7 @@ func main() {
|
|||||||
|
|
||||||
if *enableAutoUpdate {
|
if *enableAutoUpdate {
|
||||||
fmt.Println("Checking required config update")
|
fmt.Println("Checking required config update")
|
||||||
update.RunConfigUpdate(0, update.GetVersionIntFromVersionNumber(version))
|
update.RunConfigUpdate(0, update.GetVersionIntFromVersionNumber(SYSTEM_VERSION))
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupCloseHandler()
|
SetupCloseHandler()
|
||||||
@ -185,7 +123,7 @@ func main() {
|
|||||||
webminPanelMux = http.NewServeMux()
|
webminPanelMux = http.NewServeMux()
|
||||||
csrfMiddleware = csrf.Protect(
|
csrfMiddleware = csrf.Protect(
|
||||||
[]byte(nodeUUID),
|
[]byte(nodeUUID),
|
||||||
csrf.CookieName("zoraxy-csrf"),
|
csrf.CookieName(CSRF_COOKIENAME),
|
||||||
csrf.Secure(false),
|
csrf.Secure(false),
|
||||||
csrf.Path("/"),
|
csrf.Path("/"),
|
||||||
csrf.SameSite(csrf.SameSiteLaxMode),
|
csrf.SameSite(csrf.SameSiteLaxMode),
|
||||||
@ -208,11 +146,10 @@ func main() {
|
|||||||
//Start the finalize sequences
|
//Start the finalize sequences
|
||||||
finalSequence()
|
finalSequence()
|
||||||
|
|
||||||
SystemWideLogger.Println("Zoraxy started. Visit control panel at http://localhost" + *webUIPort)
|
SystemWideLogger.Println(SYSTEM_NAME + " started. Visit control panel at http://localhost" + *webUIPort)
|
||||||
err = http.ListenAndServe(*webUIPort, csrfMiddleware(webminPanelMux))
|
err = http.ListenAndServe(*webUIPort, csrfMiddleware(webminPanelMux))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,13 @@ func (a *ACMEHandler) Logf(message string, err error) {
|
|||||||
a.Logger.PrintAndLog("ACME", message, err)
|
a.Logger.PrintAndLog("ACME", message, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close closes the ACMEHandler.
|
||||||
|
// ACME Handler does not need to close anything
|
||||||
|
// Function defined for future compatibility
|
||||||
|
func (a *ACMEHandler) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ObtainCert obtains a certificate for the specified domains.
|
// ObtainCert obtains a certificate for the specified domains.
|
||||||
func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email string, caName string, caUrl string, skipTLS bool, useDNS bool, propagationTimeout int) (bool, error) {
|
func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email string, caName string, caUrl string, skipTLS bool, useDNS bool, propagationTimeout int) (bool, error) {
|
||||||
a.Logf("Obtaining certificate for: "+strings.Join(domains, ", "), nil)
|
a.Logf("Obtaining certificate for: "+strings.Join(domains, ", "), nil)
|
||||||
|
@ -354,6 +354,7 @@ func (a *AutoRenewer) CheckAndRenewCertificates() ([]string, error) {
|
|||||||
return a.renewExpiredDomains(expiredCertList)
|
return a.renewExpiredDomains(expiredCertList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the auto renewer
|
||||||
func (a *AutoRenewer) Close() {
|
func (a *AutoRenewer) Close() {
|
||||||
if a.TickerstopChan != nil {
|
if a.TickerstopChan != nil {
|
||||||
a.TickerstopChan <- true
|
a.TickerstopChan <- true
|
||||||
@ -439,7 +440,7 @@ func (a *AutoRenewer) HanldeSetEAB(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle update auto renew DNS configuration
|
// Handle update auto renew DNS configuration
|
||||||
func (a *AutoRenewer) HanldeSetDNS(w http.ResponseWriter, r *http.Request) {
|
func (a *AutoRenewer) HandleSetDNS(w http.ResponseWriter, r *http.Request) {
|
||||||
dnsProvider, err := utils.PostPara(r, "dnsProvider")
|
dnsProvider, err := utils.PostPara(r, "dnsProvider")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.SendErrorResponse(w, "dnsProvider not set")
|
utils.SendErrorResponse(w, "dnsProvider not set")
|
||||||
|
@ -9,6 +9,7 @@ package domainsniff
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -25,6 +26,30 @@ func DomainReachableWithError(domain string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if a domain have TLS but it is self-signed or expired
|
||||||
|
func DomainIsSelfSigned(domain string) (bool, error) {
|
||||||
|
//Get the certificate
|
||||||
|
conn, err := net.Dial("tcp", domain)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
//Connect with TLS using insecure skip verify
|
||||||
|
config := &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
}
|
||||||
|
tlsConn := tls.Client(conn, config)
|
||||||
|
err = tlsConn.Handshake()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the certificate is self-signed
|
||||||
|
cert := tlsConn.ConnectionState().PeerCertificates[0]
|
||||||
|
return cert.Issuer.CommonName == cert.Subject.CommonName, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Check if domain reachable
|
// Check if domain reachable
|
||||||
func DomainReachable(domain string) bool {
|
func DomainReachable(domain string) bool {
|
||||||
return DomainReachableWithError(domain) == nil
|
return DomainReachableWithError(domain) == nil
|
||||||
|
@ -85,7 +85,7 @@ func ReverseProxtInit() {
|
|||||||
|
|
||||||
dprouter, err := dynamicproxy.NewDynamicProxy(dynamicproxy.RouterOption{
|
dprouter, err := dynamicproxy.NewDynamicProxy(dynamicproxy.RouterOption{
|
||||||
HostUUID: nodeUUID,
|
HostUUID: nodeUUID,
|
||||||
HostVersion: version,
|
HostVersion: SYSTEM_VERSION,
|
||||||
Port: inboundPort,
|
Port: inboundPort,
|
||||||
UseTls: useTls,
|
UseTls: useTls,
|
||||||
ForceTLSLatest: forceLatestTLSVersion,
|
ForceTLSLatest: forceLatestTLSVersion,
|
||||||
|
@ -27,7 +27,7 @@ func FSHandler(handler http.Handler) http.Handler {
|
|||||||
Development Mode Override
|
Development Mode Override
|
||||||
=> Web root is located in /
|
=> Web root is located in /
|
||||||
*/
|
*/
|
||||||
if development && strings.HasPrefix(r.URL.Path, "/web/") {
|
if DEVELOPMENT_BUILD && strings.HasPrefix(r.URL.Path, "/web/") {
|
||||||
u, _ := url.Parse(strings.TrimPrefix(r.URL.Path, "/web"))
|
u, _ := url.Parse(strings.TrimPrefix(r.URL.Path, "/web"))
|
||||||
r.URL = u
|
r.URL = u
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ func FSHandler(handler http.Handler) http.Handler {
|
|||||||
Production Mode Override
|
Production Mode Override
|
||||||
=> Web root is located in /web
|
=> Web root is located in /web
|
||||||
*/
|
*/
|
||||||
if !development && r.URL.Path == "/" {
|
if !DEVELOPMENT_BUILD && r.URL.Path == "/" {
|
||||||
//Redirect to web UI
|
//Redirect to web UI
|
||||||
http.Redirect(w, r, "/web/", http.StatusTemporaryRedirect)
|
http.Redirect(w, r, "/web/", http.StatusTemporaryRedirect)
|
||||||
return
|
return
|
||||||
@ -93,7 +93,7 @@ func FSHandler(handler http.Handler) http.Handler {
|
|||||||
|
|
||||||
// Production path fix wrapper. Fix the path on production or development environment
|
// Production path fix wrapper. Fix the path on production or development environment
|
||||||
func ppf(relativeFilepath string) string {
|
func ppf(relativeFilepath string) string {
|
||||||
if !development {
|
if !DEVELOPMENT_BUILD {
|
||||||
return strings.ReplaceAll(filepath.Join("/web/", relativeFilepath), "\\", "/")
|
return strings.ReplaceAll(filepath.Join("/web/", relativeFilepath), "\\", "/")
|
||||||
}
|
}
|
||||||
return relativeFilepath
|
return relativeFilepath
|
||||||
@ -111,7 +111,7 @@ func handleInjectHTML(w http.ResponseWriter, r *http.Request, relativeFilepath s
|
|||||||
if len(relativeFilepath) > 0 && relativeFilepath[len(relativeFilepath)-1:] == "/" {
|
if len(relativeFilepath) > 0 && relativeFilepath[len(relativeFilepath)-1:] == "/" {
|
||||||
relativeFilepath = relativeFilepath + "index.html"
|
relativeFilepath = relativeFilepath + "index.html"
|
||||||
}
|
}
|
||||||
if development {
|
if DEVELOPMENT_BUILD {
|
||||||
//Load from disk
|
//Load from disk
|
||||||
targetFilePath := strings.ReplaceAll(filepath.Join("web/", relativeFilepath), "\\", "/")
|
targetFilePath := strings.ReplaceAll(filepath.Join("web/", relativeFilepath), "\\", "/")
|
||||||
content, err = os.ReadFile(targetFilePath)
|
content, err = os.ReadFile(targetFilePath)
|
||||||
|
46
src/start.go
46
src/start.go
@ -52,19 +52,19 @@ var (
|
|||||||
|
|
||||||
func startupSequence() {
|
func startupSequence() {
|
||||||
//Start a system wide logger and log viewer
|
//Start a system wide logger and log viewer
|
||||||
l, err := logger.NewLogger("zr", "./log")
|
l, err := logger.NewLogger(LOG_PREFIX, LOG_FOLDER)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
SystemWideLogger = l
|
SystemWideLogger = l
|
||||||
} else {
|
} else {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
LogViewer = logviewer.NewLogViewer(&logviewer.ViewerOption{
|
LogViewer = logviewer.NewLogViewer(&logviewer.ViewerOption{
|
||||||
RootFolder: "./log",
|
RootFolder: LOG_FOLDER,
|
||||||
Extension: ".log",
|
Extension: LOG_EXTENSION,
|
||||||
})
|
})
|
||||||
|
|
||||||
//Create database
|
//Create database
|
||||||
db, err := database.NewDatabase("sys.db", false)
|
db, err := database.NewDatabase(DATABASE_PATH, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -73,21 +73,21 @@ func startupSequence() {
|
|||||||
sysdb.NewTable("settings")
|
sysdb.NewTable("settings")
|
||||||
|
|
||||||
//Create tmp folder and conf folder
|
//Create tmp folder and conf folder
|
||||||
os.MkdirAll("./tmp", 0775)
|
os.MkdirAll(TMP_FOLDER, 0775)
|
||||||
os.MkdirAll("./conf/proxy/", 0775)
|
os.MkdirAll(CONF_HTTP_PROXY, 0775)
|
||||||
|
|
||||||
//Create an auth agent
|
//Create an auth agent
|
||||||
sessionKey, err := auth.GetSessionKey(sysdb, SystemWideLogger)
|
sessionKey, err := auth.GetSessionKey(sysdb, SystemWideLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
authAgent = auth.NewAuthenticationAgent(name, []byte(sessionKey), sysdb, true, SystemWideLogger, func(w http.ResponseWriter, r *http.Request) {
|
authAgent = auth.NewAuthenticationAgent(SYSTEM_NAME, []byte(sessionKey), sysdb, true, SystemWideLogger, func(w http.ResponseWriter, r *http.Request) {
|
||||||
//Not logged in. Redirecting to login page
|
//Not logged in. Redirecting to login page
|
||||||
http.Redirect(w, r, ppf("/login.html"), http.StatusTemporaryRedirect)
|
http.Redirect(w, r, ppf("/login.html"), http.StatusTemporaryRedirect)
|
||||||
})
|
})
|
||||||
|
|
||||||
//Create a TLS certificate manager
|
//Create a TLS certificate manager
|
||||||
tlsCertManager, err = tlscert.NewManager("./conf/certs", development, SystemWideLogger)
|
tlsCertManager, err = tlscert.NewManager(CONF_CERT_STORE, DEVELOPMENT_BUILD, SystemWideLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ func startupSequence() {
|
|||||||
db.NewTable("redirect")
|
db.NewTable("redirect")
|
||||||
redirectAllowRegexp := false
|
redirectAllowRegexp := false
|
||||||
db.Read("redirect", "regex", &redirectAllowRegexp)
|
db.Read("redirect", "regex", &redirectAllowRegexp)
|
||||||
redirectTable, err = redirection.NewRuleTable("./conf/redirect", redirectAllowRegexp, SystemWideLogger)
|
redirectTable, err = redirection.NewRuleTable(CONF_REDIRECTION, redirectAllowRegexp, SystemWideLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ func startupSequence() {
|
|||||||
accessController, err = access.NewAccessController(&access.Options{
|
accessController, err = access.NewAccessController(&access.Options{
|
||||||
Database: sysdb,
|
Database: sysdb,
|
||||||
GeoDB: geodbStore,
|
GeoDB: geodbStore,
|
||||||
ConfigFolder: "./conf/access",
|
ConfigFolder: CONF_ACCESS_RULE,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -154,7 +154,7 @@ func startupSequence() {
|
|||||||
//Start the static web server
|
//Start the static web server
|
||||||
staticWebServer = webserv.NewWebServer(&webserv.WebServerOptions{
|
staticWebServer = webserv.NewWebServer(&webserv.WebServerOptions{
|
||||||
Sysdb: sysdb,
|
Sysdb: sysdb,
|
||||||
Port: "5487", //Default Port
|
Port: strconv.Itoa(WEBSERV_DEFAULT_PORT), //Default Port
|
||||||
WebRoot: *staticWebServerRoot,
|
WebRoot: *staticWebServerRoot,
|
||||||
EnableDirectoryListing: true,
|
EnableDirectoryListing: true,
|
||||||
EnableWebDirManager: *allowWebFileManager,
|
EnableWebDirManager: *allowWebFileManager,
|
||||||
@ -179,7 +179,7 @@ func startupSequence() {
|
|||||||
|
|
||||||
pathRuleHandler = pathrule.NewPathRuleHandler(&pathrule.Options{
|
pathRuleHandler = pathrule.NewPathRuleHandler(&pathrule.Options{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
ConfigFolder: "./conf/rules/pathrules",
|
ConfigFolder: CONF_PATH_RULE,
|
||||||
})
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -197,7 +197,7 @@ func startupSequence() {
|
|||||||
|
|
||||||
hostName := *mdnsName
|
hostName := *mdnsName
|
||||||
if hostName == "" {
|
if hostName == "" {
|
||||||
hostName = "zoraxy_" + nodeUUID
|
hostName = MDNS_HOSTNAME_PREFIX + nodeUUID
|
||||||
} else {
|
} else {
|
||||||
//Trim off the suffix
|
//Trim off the suffix
|
||||||
hostName = strings.TrimSuffix(hostName, ".local")
|
hostName = strings.TrimSuffix(hostName, ".local")
|
||||||
@ -206,24 +206,24 @@ func startupSequence() {
|
|||||||
mdnsScanner, err = mdns.NewMDNS(mdns.NetworkHost{
|
mdnsScanner, err = mdns.NewMDNS(mdns.NetworkHost{
|
||||||
HostName: hostName,
|
HostName: hostName,
|
||||||
Port: portInt,
|
Port: portInt,
|
||||||
Domain: "zoraxy.aroz.org",
|
Domain: MDNS_IDENTIFY_DOMAIN,
|
||||||
Model: "Network Gateway",
|
Model: MDNS_IDENTIFY_DEVICE_TYPE,
|
||||||
UUID: nodeUUID,
|
UUID: nodeUUID,
|
||||||
Vendor: "imuslab.com",
|
Vendor: MDNS_IDENTIFY_VENDOR,
|
||||||
BuildVersion: version,
|
BuildVersion: SYSTEM_VERSION,
|
||||||
}, "")
|
}, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
SystemWideLogger.Println("Unable to startup mDNS service. Disabling mDNS services")
|
SystemWideLogger.Println("Unable to startup mDNS service. Disabling mDNS services")
|
||||||
} else {
|
} else {
|
||||||
//Start initial scanning
|
//Start initial scanning
|
||||||
go func() {
|
go func() {
|
||||||
hosts := mdnsScanner.Scan(30, "")
|
hosts := mdnsScanner.Scan(MDNS_SCAN_TIMEOUT, "")
|
||||||
previousmdnsScanResults = hosts
|
previousmdnsScanResults = hosts
|
||||||
SystemWideLogger.Println("mDNS Startup scan completed")
|
SystemWideLogger.Println("mDNS Startup scan completed")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
//Create a ticker to update mDNS results every 5 minutes
|
//Create a ticker to update mDNS results every 5 minutes
|
||||||
ticker := time.NewTicker(15 * time.Minute)
|
ticker := time.NewTicker(MDNS_SCAN_UPDATE_INTERVAL * time.Minute)
|
||||||
stopChan := make(chan bool)
|
stopChan := make(chan bool)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
@ -231,7 +231,7 @@ func startupSequence() {
|
|||||||
case <-stopChan:
|
case <-stopChan:
|
||||||
ticker.Stop()
|
ticker.Stop()
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
hosts := mdnsScanner.Scan(30, "")
|
hosts := mdnsScanner.Scan(MDNS_SCAN_TIMEOUT, "")
|
||||||
previousmdnsScanResults = hosts
|
previousmdnsScanResults = hosts
|
||||||
SystemWideLogger.Println("mDNS scan result updated")
|
SystemWideLogger.Println("mDNS scan result updated")
|
||||||
}
|
}
|
||||||
@ -265,7 +265,7 @@ func startupSequence() {
|
|||||||
//Create TCP Proxy Manager
|
//Create TCP Proxy Manager
|
||||||
streamProxyManager, err = streamproxy.NewStreamProxy(&streamproxy.Options{
|
streamProxyManager, err = streamproxy.NewStreamProxy(&streamproxy.Options{
|
||||||
AccessControlHandler: accessController.DefaultAccessRule.AllowConnectionAccess,
|
AccessControlHandler: accessController.DefaultAccessRule.AllowConnectionAccess,
|
||||||
ConfigStore: "./conf/streamproxy",
|
ConfigStore: CONF_STREAM_PROXY,
|
||||||
Logger: SystemWideLogger,
|
Logger: SystemWideLogger,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -303,8 +303,8 @@ func startupSequence() {
|
|||||||
sysdb.NewTable("acmepref")
|
sysdb.NewTable("acmepref")
|
||||||
acmeHandler = initACME()
|
acmeHandler = initACME()
|
||||||
acmeAutoRenewer, err = acme.NewAutoRenewer(
|
acmeAutoRenewer, err = acme.NewAutoRenewer(
|
||||||
"./conf/acme_conf.json",
|
ACME_AUTORENEW_CONFIG_PATH,
|
||||||
"./conf/certs/",
|
CONF_CERT_STORE,
|
||||||
int64(*acmeAutoRenewInterval),
|
int64(*acmeAutoRenewInterval),
|
||||||
*acmeCertAutoRenewDays,
|
*acmeCertAutoRenewDays,
|
||||||
acmeHandler,
|
acmeHandler,
|
||||||
|
6
src/web/robots.txt
Normal file
6
src/web/robots.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# robots.txt for Zoraxy project
|
||||||
|
# In general, you should not expose the management interface to the internet.
|
||||||
|
# In case you do, this file (hopefully) protects you from web crawlers.
|
||||||
|
|
||||||
|
User-agent: *
|
||||||
|
Disallow: /
|
@ -368,9 +368,9 @@ func HandleZoraxyInfo(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
info := ZoraxyInfo{
|
info := ZoraxyInfo{
|
||||||
Version: version,
|
Version: SYSTEM_VERSION,
|
||||||
NodeUUID: nodeUUID,
|
NodeUUID: nodeUUID,
|
||||||
Development: development,
|
Development: DEVELOPMENT_BUILD,
|
||||||
BootTime: bootTime,
|
BootTime: bootTime,
|
||||||
EnableSshLoopback: *allowSshLoopback,
|
EnableSshLoopback: *allowSshLoopback,
|
||||||
ZerotierConnected: ganManager.ControllerID != "",
|
ZerotierConnected: ganManager.ControllerID != "",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user