From 156fa5dacecd9ce492df76c8f8b82e6078519f98 Mon Sep 17 00:00:00 2001 From: tobychui Date: Fri, 20 Oct 2023 11:01:28 +0800 Subject: [PATCH 1/6] Bug fix + Added potential fix for #67 + Update version number + Changed default static web port to 5487 so it is even more unlikely to be used + --- src/main.go | 4 +-- src/start.go | 2 +- src/web/components/rproot.html | 63 ++++++++++++++++++++++++++++----- src/web/components/webserv.html | 4 +-- 4 files changed, 59 insertions(+), 14 deletions(-) diff --git a/src/main.go b/src/main.go index 4177a75..45d5ec5 100644 --- a/src/main.go +++ b/src/main.go @@ -47,9 +47,9 @@ var allowWebFileManager = flag.Bool("webfm", true, "Enable web file manager for var ( name = "Zoraxy" - version = "2.6.7" + version = "2.6.8" nodeUUID = "generic" - development = false //Set this to false to use embedded web fs + development = true //Set this to false to use embedded web fs bootTime = time.Now().Unix() /* diff --git a/src/start.go b/src/start.go index 4dd4aa8..6d210cb 100644 --- a/src/start.go +++ b/src/start.go @@ -220,7 +220,7 @@ func startupSequence() { staticWebServer = webserv.NewWebServer(&webserv.WebServerOptions{ Sysdb: sysdb, - Port: "8081", //Default Port + Port: "5487", //Default Port WebRoot: *staticWebServerRoot, EnableDirectoryListing: true, EnableWebDirManager: *allowWebFileManager, diff --git a/src/web/components/rproot.html b/src/web/components/rproot.html index 6e0bfc7..57ababf 100644 --- a/src/web/components/rproot.html +++ b/src/web/components/rproot.html @@ -75,13 +75,13 @@ $("#rootReqTLS").parent().addClass("disabled"); //Check if web server is enabled. If not, ask if the user want to enable it - if (!$("#webserv_enable").parent().checkbox("is checked")){ + /*if (!$("#webserv_enable").parent().checkbox("is checked")){ confirmBox("Enable static web server now?", function(choice){ if (choice == true){ $("#webserv_enable").parent().checkbox("set checked"); } }); - } + }*/ }else{ $("#rootReqTLS").parent().removeClass("disabled"); $("#proxyRoot").parent().removeClass("disabled"); @@ -89,7 +89,7 @@ } } - function initRootInfo(){ + function initRootInfo(callback=undefined){ $.get("/api/proxy/list?type=root", function(data){ if (data == null){ @@ -97,11 +97,38 @@ $("#proxyRoot").val(data.Domain); checkRootRequireTLS(data.Domain); } + + if (callback != undefined){ + callback(); + } + }); + } + initRootInfo(function(){ + updateWebServerLinkSettings(); + }); + + //Update the current web server port settings + function updateWebServerLinkSettings(){ + isUsingStaticWebServerAsRoot(function(isUsingWebServ){ + if (isUsingWebServ){ + $(".webservRootDisabled").addClass("disabled"); + }else{ + $(".webservRootDisabled").removeClass("disabled"); + } + }) + } + + function isUsingStaticWebServerAsRoot(callback){ + let currentProxyRoot = $("#proxyRoot").val().trim(); + $.get("/api/webserv/status", function(webservStatus){ + if (currentProxyRoot == "127.0.0.1:" + webservStatus.ListeningPort || currentProxyRoot == "localhost:" + webservStatus.ListeningPort){ + return callback(true); + } + return callback(false); }); } - initRootInfo(); - + function updateRootSettingStates(){ $.get("/api/cert/tls", function(data){ if (data == true){ @@ -111,6 +138,7 @@ } }); } + //Bind event to tab switch tabSwitchEventBind["setroot"] = function(){ //On switch over to this page, update root info @@ -137,11 +165,12 @@ let useRedirect = $("#unsetRedirect")[0].checked; updateRedirectionDomainSettingInputBox(useRedirect); }); - }) + }); } checkCustomRedirectForUnsetSubd(); + //Check if the given domain will redirect to https function checkRootRequireTLS(targetDomain){ //Trim off the http or https from the origin if (targetDomain.startsWith("http://")){ @@ -168,7 +197,7 @@ }) } - + //Set the new proxy root option function setProxyRoot(){ var newpr = $("#proxyRoot").val(); if (newpr.trim() == ""){ @@ -189,8 +218,24 @@ msgbox(data.error, false, 5000); }else{ //OK - initRootInfo(); - msgbox("Proxy Root Updated") + initRootInfo(function(){ + //Check if WebServ is enabled + isUsingStaticWebServerAsRoot(function(isUsingWebServ){ + if (isUsingWebServ){ + //Force enable static web server + //See webserv.html for details + setWebServerRunningState(true); + } + + setTimeout(function(){ + //Update the checkbox + updateWebServerLinkSettings(); + msgbox("Proxy Root Updated"); + }, 1000); + + }) + }); + } } }); diff --git a/src/web/components/webserv.html b/src/web/components/webserv.html index a0e201f..6f94822 100644 --- a/src/web/components/webserv.html +++ b/src/web/components/webserv.html @@ -17,7 +17,7 @@

Web Server Settings

-
+
@@ -37,7 +37,7 @@ See the -webserv flag for more details.
-
+
Use http://127.0.0.1:8081 in proxy rules to access the web server From 172479e4fbfad48d4b7e7ca18126387a6f41b72b Mon Sep 17 00:00:00 2001 From: Toby Chui Date: Fri, 20 Oct 2023 13:44:47 +0800 Subject: [PATCH 2/6] Added default HTTP/2 Mode + Added automatic HTTP/2 switch to TLS mode (Related to #40) --- src/mod/dynamicproxy/dynamicproxy.go | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/mod/dynamicproxy/dynamicproxy.go b/src/mod/dynamicproxy/dynamicproxy.go index 8b5d750..4c280ea 100644 --- a/src/mod/dynamicproxy/dynamicproxy.go +++ b/src/mod/dynamicproxy/dynamicproxy.go @@ -95,15 +95,21 @@ func (router *Router) StartProxyService() error { } if router.Option.UseTls { - //Serve with TLS mode - ln, err := tls.Listen("tcp", ":"+strconv.Itoa(router.Option.Port), config) - if err != nil { - log.Println(err) - router.Running = false - return err + /* + //Serve with TLS mode + ln, err := tls.Listen("tcp", ":"+strconv.Itoa(router.Option.Port), config) + if err != nil { + log.Println(err) + router.Running = false + return err + } + router.tlsListener = ln + */ + router.server = &http.Server{ + Addr: ":" + strconv.Itoa(router.Option.Port), + Handler: router.mux, + TLSConfig: config, } - router.tlsListener = ln - router.server = &http.Server{Addr: ":" + strconv.Itoa(router.Option.Port), Handler: router.mux} router.Running = true if router.Option.Port != 80 && router.Option.ForceHttpsRedirect { @@ -143,7 +149,7 @@ func (router *Router) StartProxyService() error { if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { //Unable to startup port 80 listener. Handle shutdown process gracefully stopChan <- true - log.Fatalf("Could not start server: %v\n", err) + log.Fatalf("Could not start redirection server: %v\n", err) } }() router.tlsRedirectStop = stopChan @@ -152,8 +158,8 @@ func (router *Router) StartProxyService() error { //Start the TLS server log.Println("Reverse proxy service started in the background (TLS mode)") go func() { - if err := router.server.Serve(ln); err != nil && err != http.ErrServerClosed { - log.Fatalf("Could not start server: %v\n", err) + if err := router.server.ListenAndServeTLS("", ""); err != nil && err != http.ErrServerClosed { + log.Fatalf("Could not start proxy server: %v\n", err) } }() } else { From e363d55899fe5a536c36e5d018bcd8ef1be0b5eb Mon Sep 17 00:00:00 2001 From: Toby Chui Date: Sat, 25 Nov 2023 12:50:30 +0800 Subject: [PATCH 3/6] Fixed #77 and added systemwide logger + Added system wide logger (wip) + Fixed issue #77 uptime monitor bug + Added backend options for bypass global TLS (or allow per rule TLS settings, wip) + --- src/acme.go | 13 ++- src/cert.go | 11 ++- src/config.go | 18 ++-- src/main.go | 14 +++- src/mod/dynamicproxy/subdomain.go | 1 + src/mod/info/logger/logger.go | 103 +++++++++++++++++++++++ src/mod/info/logviewer/logviewer.go | 122 ++++++++++++++++++++++++++++ src/reverseproxy.go | 50 ++++++++---- src/start.go | 18 ++-- src/web/components/rproot.html | 2 + src/web/components/rules.html | 8 ++ src/web/components/uptime.html | 27 +++++- src/wrappers.go | 19 ++++- 13 files changed, 356 insertions(+), 50 deletions(-) create mode 100644 src/mod/info/logger/logger.go create mode 100644 src/mod/info/logviewer/logviewer.go diff --git a/src/acme.go b/src/acme.go index a04a257..cdd04dc 100644 --- a/src/acme.go +++ b/src/acme.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "io" - "log" "math/rand" "net/http" "regexp" @@ -29,7 +28,7 @@ func getRandomPort(minPort int) int { // init the new ACME instance func initACME() *acme.ACMEHandler { - log.Println("Starting ACME handler") + SystemWideLogger.Println("Starting ACME handler") rand.Seed(time.Now().UnixNano()) // Generate a random port above 30000 port := getRandomPort(30000) @@ -44,7 +43,7 @@ func initACME() *acme.ACMEHandler { // create the special routing rule for ACME func acmeRegisterSpecialRoutingRule() { - log.Println("Assigned temporary port:" + acmeHandler.Getport()) + SystemWideLogger.Println("Assigned temporary port:" + acmeHandler.Getport()) err := dynamicProxyRouter.AddRoutingRules(&dynamicproxy.RoutingRule{ ID: "acme-autorenew", @@ -79,7 +78,7 @@ func acmeRegisterSpecialRoutingRule() { }) if err != nil { - log.Println("[Err] " + err.Error()) + SystemWideLogger.PrintAndLog("ACME", "Unable register temp port for DNS resolver", err) } } @@ -89,7 +88,7 @@ func AcmeCheckAndHandleRenewCertificate(w http.ResponseWriter, r *http.Request) if dynamicProxyRouter.Option.Port == 443 { //Enable port 80 to 443 redirect if !dynamicProxyRouter.Option.ForceHttpsRedirect { - log.Println("Temporary enabling HTTP to HTTPS redirect for ACME certificate renew requests") + SystemWideLogger.Println("Temporary enabling HTTP to HTTPS redirect for ACME certificate renew requests") dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(true) } else { //Set this to true, so after renew, do not turn it off @@ -110,7 +109,7 @@ func AcmeCheckAndHandleRenewCertificate(w http.ResponseWriter, r *http.Request) if dynamicProxyRouter.Option.Port == 443 { if !isForceHttpsRedirectEnabledOriginally { //Default is off. Turn the redirection off - log.Println("Restoring HTTP to HTTPS redirect settings") + SystemWideLogger.PrintAndLog("ACME", "Restoring HTTP to HTTPS redirect settings", nil) dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(false) } } @@ -130,7 +129,7 @@ func HandleACMEPreferredCA(w http.ResponseWriter, r *http.Request) { acme.IsSupportedCA(ca) //Set the new config sysdb.Write("acmepref", "prefca", ca) - log.Println("Updating prefered ACME CA to " + ca) + SystemWideLogger.Println("Updating prefered ACME CA to " + ca) utils.SendOK(w) } diff --git a/src/cert.go b/src/cert.go index e0f3464..567fd7c 100644 --- a/src/cert.go +++ b/src/cert.go @@ -6,7 +6,6 @@ import ( "encoding/pem" "fmt" "io" - "log" "net/http" "os" "path/filepath" @@ -128,7 +127,7 @@ func handleListDomains(w http.ResponseWriter, r *http.Request) { certBtyes, err := os.ReadFile(certFilepath) if err != nil { // Unable to load this file - log.Println("Unable to load certificate: " + certFilepath) + SystemWideLogger.PrintAndLog("TLS", "Unable to load certificate: "+certFilepath, err) continue } else { // Cert loaded. Check its expiry time @@ -182,11 +181,11 @@ func handleToggleTLSProxy(w http.ResponseWriter, r *http.Request) { } else { if newState == "true" { sysdb.Write("settings", "usetls", true) - log.Println("Enabling TLS mode on reverse proxy") + SystemWideLogger.Println("Enabling TLS mode on reverse proxy") dynamicProxyRouter.UpdateTLSSetting(true) } else if newState == "false" { sysdb.Write("settings", "usetls", false) - log.Println("Disabling TLS mode on reverse proxy") + SystemWideLogger.Println("Disabling TLS mode on reverse proxy") dynamicProxyRouter.UpdateTLSSetting(false) } else { utils.SendErrorResponse(w, "invalid state given. Only support true or false") @@ -213,11 +212,11 @@ func handleSetTlsRequireLatest(w http.ResponseWriter, r *http.Request) { } else { if newState == "true" { sysdb.Write("settings", "forceLatestTLS", true) - log.Println("Updating minimum TLS version to v1.2 or above") + SystemWideLogger.Println("Updating minimum TLS version to v1.2 or above") dynamicProxyRouter.UpdateTLSVersion(true) } else if newState == "false" { sysdb.Write("settings", "forceLatestTLS", false) - log.Println("Updating minimum TLS version to v1.0 or above") + SystemWideLogger.Println("Updating minimum TLS version to v1.0 or above") dynamicProxyRouter.UpdateTLSVersion(false) } else { utils.SendErrorResponse(w, "invalid state given") diff --git a/src/config.go b/src/config.go index 9150476..c012467 100644 --- a/src/config.go +++ b/src/config.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "io" - "log" "net/http" "os" "path/filepath" @@ -29,6 +28,7 @@ type Record struct { Rootname string ProxyTarget string UseTLS bool + BypassGlobalTLS bool SkipTlsValidation bool RequireBasicAuth bool BasicAuthCredentials []*dynamicproxy.BasicAuthCredentials @@ -61,11 +61,11 @@ func SaveReverseProxyEndpointToFile(proxyEndpoint *dynamicproxy.ProxyEndpoint) e func RemoveReverseProxyConfigFile(rootname string) error { filename := getFilenameFromRootName(rootname) removePendingFile := strings.ReplaceAll(filepath.Join("./conf/proxy/", filename), "\\", "/") - log.Println("Config Removed: ", removePendingFile) + SystemWideLogger.Println("Config Removed: ", removePendingFile) if utils.FileExists(removePendingFile) { err := os.Remove(removePendingFile) if err != nil { - log.Println(err.Error()) + SystemWideLogger.PrintAndLog("Proxy", "Unabel to remove config file", err) return err } } @@ -81,6 +81,7 @@ func LoadReverseProxyConfig(filename string) (*Record, error) { Rootname: "", ProxyTarget: "", UseTLS: false, + BypassGlobalTLS: false, SkipTlsValidation: false, RequireBasicAuth: false, BasicAuthCredentials: []*dynamicproxy.BasicAuthCredentials{}, @@ -109,6 +110,7 @@ func ConvertProxyEndpointToRecord(targetProxyEndpoint *dynamicproxy.ProxyEndpoin Rootname: targetProxyEndpoint.RootOrMatchingDomain, ProxyTarget: targetProxyEndpoint.Domain, UseTLS: targetProxyEndpoint.RequireTLS, + BypassGlobalTLS: targetProxyEndpoint.BypassGlobalTLS, SkipTlsValidation: targetProxyEndpoint.SkipCertValidations, RequireBasicAuth: targetProxyEndpoint.RequireBasicAuth, BasicAuthCredentials: targetProxyEndpoint.BasicAuthCredentials, @@ -191,14 +193,14 @@ func ExportConfigAsZip(w http.ResponseWriter, r *http.Request) { //Also zip in the sysdb zipFile, err := zipWriter.Create("sys.db") if err != nil { - log.Println("[Backup] Unable to zip sysdb: " + err.Error()) + SystemWideLogger.PrintAndLog("Backup", "Unable to zip sysdb", err) return } // Open the file on disk file, err := os.Open("sys.db") if err != nil { - log.Println("[Backup] Unable to open sysdb: " + err.Error()) + SystemWideLogger.PrintAndLog("Backup", "Unable to open sysdb", err) return } defer file.Close() @@ -206,7 +208,7 @@ func ExportConfigAsZip(w http.ResponseWriter, r *http.Request) { // Copy the file contents to the zip file _, err = io.Copy(zipFile, file) if err != nil { - log.Println(err) + SystemWideLogger.Println(err) return } @@ -311,12 +313,12 @@ func ImportConfigFromZip(w http.ResponseWriter, r *http.Request) { // Send a success response w.WriteHeader(http.StatusOK) - log.Println("Configuration restored") + SystemWideLogger.Println("Configuration restored") fmt.Fprintln(w, "Configuration restored") if restoreDatabase { go func() { - log.Println("Database altered. Restarting in 3 seconds...") + SystemWideLogger.Println("Database altered. Restarting in 3 seconds...") time.Sleep(3 * time.Second) os.Exit(0) }() diff --git a/src/main.go b/src/main.go index 45d5ec5..4803065 100644 --- a/src/main.go +++ b/src/main.go @@ -20,6 +20,7 @@ import ( "imuslab.com/zoraxy/mod/email" "imuslab.com/zoraxy/mod/ganserv" "imuslab.com/zoraxy/mod/geodb" + "imuslab.com/zoraxy/mod/info/logger" "imuslab.com/zoraxy/mod/mdns" "imuslab.com/zoraxy/mod/netstat" "imuslab.com/zoraxy/mod/pathrule" @@ -44,6 +45,7 @@ var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL cert 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 logOutputToFile = flag.Bool("log", true, "Log terminal output to file") var ( name = "Zoraxy" @@ -80,8 +82,9 @@ var ( staticWebServer *webserv.WebServer //Static web server for hosting simple stuffs //Helper modules - EmailSender *email.Sender //Email sender that handle email sending - AnalyticLoader *analytic.DataLoader //Data loader for Zoraxy Analytic + EmailSender *email.Sender //Email sender that handle email sending + AnalyticLoader *analytic.DataLoader //Data loader for Zoraxy Analytic + SystemWideLogger *logger.Logger //Logger for Zoraxy ) // Kill signal handler. Do something before the system the core terminate. @@ -116,6 +119,9 @@ func ShutdownSeq() { fmt.Println("- Cleaning up tmp files") os.RemoveAll("./tmp") + fmt.Println("- Closing system wide logger") + SystemWideLogger.Close() + //Close database, final fmt.Println("- Stopping system database") sysdb.Close() @@ -151,7 +157,7 @@ func main() { } uuidBytes, err := os.ReadFile(uuidRecord) if err != nil { - log.Println("Unable to read system uuid from file system") + SystemWideLogger.PrintAndLog("ZeroTier", "Unable to read system uuid from file system", nil) panic(err) } nodeUUID = string(uuidBytes) @@ -173,7 +179,7 @@ func main() { //Start the finalize sequences finalSequence() - log.Println("Zoraxy started. Visit control panel at http://localhost" + handler.Port) + SystemWideLogger.Println("Zoraxy started. Visit control panel at http://localhost" + handler.Port) err = http.ListenAndServe(handler.Port, nil) if err != nil { diff --git a/src/mod/dynamicproxy/subdomain.go b/src/mod/dynamicproxy/subdomain.go index 9012724..f01e541 100644 --- a/src/mod/dynamicproxy/subdomain.go +++ b/src/mod/dynamicproxy/subdomain.go @@ -38,6 +38,7 @@ func (router *Router) AddSubdomainRoutingService(options *SubdOptions) error { Domain: domain, RequireTLS: options.RequireTLS, Proxy: proxy, + BypassGlobalTLS: options.BypassGlobalTLS, SkipCertValidations: options.SkipCertValidations, RequireBasicAuth: options.RequireBasicAuth, BasicAuthCredentials: options.BasicAuthCredentials, diff --git a/src/mod/info/logger/logger.go b/src/mod/info/logger/logger.go new file mode 100644 index 0000000..bc69ab4 --- /dev/null +++ b/src/mod/info/logger/logger.go @@ -0,0 +1,103 @@ +package logger + +import ( + "fmt" + "log" + "os" + "path/filepath" + "strconv" + "time" +) + +/* + Zoraxy Logger + + This script is designed to make a managed log for the Zoraxy + and replace the ton of log.Println in the system core +*/ + +type Logger struct { + LogToFile bool //Set enable write to file + Prefix string //Prefix for log files + LogFolder string //Folder to store the log file + CurrentLogFile string //Current writing filename + file *os.File +} + +func NewLogger(logFilePrefix string, logFolder string, logToFile bool) (*Logger, error) { + err := os.MkdirAll(logFolder, 0775) + if err != nil { + return nil, err + } + + thisLogger := Logger{ + LogToFile: logToFile, + Prefix: logFilePrefix, + LogFolder: logFolder, + } + + logFilePath := thisLogger.getLogFilepath() + f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755) + if err != nil { + return nil, err + } + thisLogger.CurrentLogFile = logFilePath + thisLogger.file = f + return &thisLogger, nil +} + +func (l *Logger) getLogFilepath() string { + year, month, _ := time.Now().Date() + return filepath.Join(l.LogFolder, l.Prefix+"_"+strconv.Itoa(year)+"-"+strconv.Itoa(int(month))+".log") +} + +// PrintAndLog will log the message to file and print the log to STDOUT +func (l *Logger) PrintAndLog(title string, message string, originalError error) { + go func() { + l.Log(title, message, originalError) + }() + log.Println("[" + title + "] " + message) +} + +// Println is a fast snap-in replacement for log.Println +func (l *Logger) Println(v ...interface{}) { + //Convert the array of interfaces into string + message := fmt.Sprint(v...) + go func() { + l.Log("info", string(message), nil) + }() + log.Println("[INFO] " + string(message)) +} + +func (l *Logger) Log(title string, errorMessage string, originalError error) { + l.ValidateAndUpdateLogFilepath() + if l.LogToFile { + if originalError == nil { + l.file.WriteString(time.Now().Format("2006-01-02 15:04:05.000000") + "|" + fmt.Sprintf("%-16s", title) + " [INFO]" + errorMessage + "\n") + } else { + l.file.WriteString(time.Now().Format("2006-01-02 15:04:05.000000") + "|" + fmt.Sprintf("%-16s", title) + " [ERROR]" + errorMessage + " " + originalError.Error() + "\n") + } + } + +} + +// Validate if the logging target is still valid (detect any months change) +func (l *Logger) ValidateAndUpdateLogFilepath() { + expectedCurrentLogFilepath := l.getLogFilepath() + if l.CurrentLogFile != expectedCurrentLogFilepath { + //Change of month. Update to a new log file + l.file.Close() + f, err := os.OpenFile(expectedCurrentLogFilepath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755) + if err != nil { + log.Println("[Logger] Unable to create new log. Logging to file disabled.") + l.LogToFile = false + return + } + l.CurrentLogFile = expectedCurrentLogFilepath + l.file = f + } +} + +func (l *Logger) Close() { + l.file.Close() +} diff --git a/src/mod/info/logviewer/logviewer.go b/src/mod/info/logviewer/logviewer.go new file mode 100644 index 0000000..24f0e19 --- /dev/null +++ b/src/mod/info/logviewer/logviewer.go @@ -0,0 +1,122 @@ +package logviewer + +import ( + "encoding/json" + "errors" + "io/fs" + "net/http" + "os" + "path/filepath" + "strings" + + "imuslab.com/zoraxy/mod/utils" +) + +type ViewerOption struct { + RootFolder string //The root folder to scan for log + Extension string //The extension the root files use, include the . in your ext (e.g. .log) +} + +type Viewer struct { + option *ViewerOption +} + +type LogFile struct { + Title string + Filename string + Fullpath string + Filesize int64 +} + +func NewLogViewer(option *ViewerOption) *Viewer { + return &Viewer{option: option} +} + +/* + Log Request Handlers +*/ +//List all the log files in the log folder. Return in map[string]LogFile format +func (v *Viewer) HandleListLog(w http.ResponseWriter, r *http.Request) { + logFiles := v.ListLogFiles(false) + js, _ := json.Marshal(logFiles) + utils.SendJSONResponse(w, string(js)) +} + +// Read log of a given catergory and filename +// Require GET varaible: file and catergory +func (v *Viewer) HandleReadLog(w http.ResponseWriter, r *http.Request) { + filename, err := utils.GetPara(r, "file") + if err != nil { + utils.SendErrorResponse(w, "invalid filename given") + return + } + + catergory, err := utils.GetPara(r, "catergory") + if err != nil { + utils.SendErrorResponse(w, "invalid catergory given") + return + } + + content, err := v.LoadLogFile(strings.TrimSpace(filepath.Base(catergory)), strings.TrimSpace(filepath.Base(filename))) + if err != nil { + utils.SendErrorResponse(w, err.Error()) + return + } + + utils.SendTextResponse(w, content) +} + +/* + Log Access Functions +*/ + +func (v *Viewer) ListLogFiles(showFullpath bool) map[string][]*LogFile { + result := map[string][]*LogFile{} + filepath.WalkDir(v.option.RootFolder, func(path string, di fs.DirEntry, err error) error { + if filepath.Ext(path) == v.option.Extension { + catergory := filepath.Base(filepath.Dir(path)) + logList, ok := result[catergory] + if !ok { + //this catergory hasn't been scanned before. + logList = []*LogFile{} + } + + fullpath := filepath.ToSlash(path) + if !showFullpath { + fullpath = "" + } + + st, err := os.Stat(path) + if err != nil { + return nil + } + + logList = append(logList, &LogFile{ + Title: strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)), + Filename: filepath.Base(path), + Fullpath: fullpath, + Filesize: st.Size(), + }) + + result[catergory] = logList + } + + return nil + }) + return result +} + +func (v *Viewer) LoadLogFile(catergory string, filename string) (string, error) { + logFilepath := filepath.Join(v.option.RootFolder, catergory, filename) + if utils.FileExists(logFilepath) { + //Load it + content, err := os.ReadFile(logFilepath) + if err != nil { + return "", err + } + + return string(content), nil + } else { + return "", errors.New("log file not found") + } +} diff --git a/src/reverseproxy.go b/src/reverseproxy.go index 43c66de..16196a9 100644 --- a/src/reverseproxy.go +++ b/src/reverseproxy.go @@ -2,7 +2,6 @@ package main import ( "encoding/json" - "log" "net/http" "path/filepath" "sort" @@ -25,33 +24,33 @@ func ReverseProxtInit() { inboundPort := 80 if sysdb.KeyExists("settings", "inbound") { sysdb.Read("settings", "inbound", &inboundPort) - log.Println("Serving inbound port ", inboundPort) + SystemWideLogger.Println("Serving inbound port ", inboundPort) } else { - log.Println("Inbound port not set. Using default (80)") + SystemWideLogger.Println("Inbound port not set. Using default (80)") } useTls := false sysdb.Read("settings", "usetls", &useTls) if useTls { - log.Println("TLS mode enabled. Serving proxxy request with TLS") + SystemWideLogger.Println("TLS mode enabled. Serving proxxy request with TLS") } else { - log.Println("TLS mode disabled. Serving proxy request with plain http") + SystemWideLogger.Println("TLS mode disabled. Serving proxy request with plain http") } forceLatestTLSVersion := false sysdb.Read("settings", "forceLatestTLS", &forceLatestTLSVersion) if forceLatestTLSVersion { - log.Println("Force latest TLS mode enabled. Minimum TLS LS version is set to v1.2") + SystemWideLogger.Println("Force latest TLS mode enabled. Minimum TLS LS version is set to v1.2") } else { - log.Println("Force latest TLS mode disabled. Minimum TLS version is set to v1.0") + SystemWideLogger.Println("Force latest TLS mode disabled. Minimum TLS version is set to v1.0") } forceHttpsRedirect := false sysdb.Read("settings", "redirect", &forceHttpsRedirect) if forceHttpsRedirect { - log.Println("Force HTTPS mode enabled") + SystemWideLogger.Println("Force HTTPS mode enabled") } else { - log.Println("Force HTTPS mode disabled") + SystemWideLogger.Println("Force HTTPS mode disabled") } dprouter, err := dynamicproxy.NewDynamicProxy(dynamicproxy.RouterOption{ @@ -67,7 +66,7 @@ func ReverseProxtInit() { WebDirectory: *staticWebServerRoot, }) if err != nil { - log.Println(err.Error()) + SystemWideLogger.PrintAndLog("Proxy", "Unable to create dynamic proxy router", err) return } @@ -78,7 +77,7 @@ func ReverseProxtInit() { for _, conf := range confs { record, err := LoadReverseProxyConfig(conf) if err != nil { - log.Println("Failed to load "+filepath.Base(conf), err.Error()) + SystemWideLogger.PrintAndLog("Proxy", "Failed to load config file: "+filepath.Base(conf), err) return } @@ -92,6 +91,7 @@ func ReverseProxtInit() { MatchingDomain: record.Rootname, Domain: record.ProxyTarget, RequireTLS: record.UseTLS, + BypassGlobalTLS: record.BypassGlobalTLS, SkipCertValidations: record.SkipTlsValidation, RequireBasicAuth: record.RequireBasicAuth, BasicAuthCredentials: record.BasicAuthCredentials, @@ -102,13 +102,14 @@ func ReverseProxtInit() { RootName: record.Rootname, Domain: record.ProxyTarget, RequireTLS: record.UseTLS, + BypassGlobalTLS: record.BypassGlobalTLS, SkipCertValidations: record.SkipTlsValidation, RequireBasicAuth: record.RequireBasicAuth, BasicAuthCredentials: record.BasicAuthCredentials, BasicAuthExceptionRules: record.BasicAuthExceptionRules, }) } else { - log.Println("Unsupported endpoint type: " + record.ProxyType + ". Skipping " + filepath.Base(conf)) + SystemWideLogger.PrintAndLog("Proxy", "Unsupported endpoint type: "+record.ProxyType+". Skipping "+filepath.Base(conf), nil) } } @@ -117,7 +118,7 @@ func ReverseProxtInit() { //reverse proxy server in front of this service time.Sleep(300 * time.Millisecond) dynamicProxyRouter.StartProxyService() - log.Println("Dynamic Reverse Proxy service started") + SystemWideLogger.Println("Dynamic Reverse Proxy service started") //Add all proxy services to uptime monitor //Create a uptime monitor service @@ -128,7 +129,7 @@ func ReverseProxtInit() { Interval: 300, //5 minutes MaxRecordsStore: 288, //1 day }) - log.Println("Uptime Monitor background service started") + SystemWideLogger.Println("Uptime Monitor background service started") }() } @@ -180,6 +181,13 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) { useTLS := (tls == "true") + bypassGlobalTLS, _ := utils.PostPara(r, "bypassGlobalTLS") + if bypassGlobalTLS == "" { + bypassGlobalTLS = "false" + } + + useBypassGlobalTLS := bypassGlobalTLS == "true" + stv, _ := utils.PostPara(r, "tlsval") if stv == "" { stv = "false" @@ -240,6 +248,7 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) { RootName: vdir, Domain: endpoint, RequireTLS: useTLS, + BypassGlobalTLS: useBypassGlobalTLS, SkipCertValidations: skipTlsValidation, RequireBasicAuth: requireBasicAuth, BasicAuthCredentials: basicAuthCredentials, @@ -257,6 +266,7 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) { MatchingDomain: subdomain, Domain: endpoint, RequireTLS: useTLS, + BypassGlobalTLS: useBypassGlobalTLS, SkipCertValidations: skipTlsValidation, RequireBasicAuth: requireBasicAuth, BasicAuthCredentials: basicAuthCredentials, @@ -281,6 +291,7 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) { Rootname: rootname, ProxyTarget: endpoint, UseTLS: useTLS, + BypassGlobalTLS: useBypassGlobalTLS, SkipTlsValidation: skipTlsValidation, RequireBasicAuth: requireBasicAuth, BasicAuthCredentials: basicAuthCredentials, @@ -385,6 +396,10 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) { BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials, } SaveReverseProxyConfigToFile(&thisProxyConfigRecord) + + //Update uptime monitor + UpdateUptimeMonitorTargets() + utils.SendOK(w) } @@ -417,6 +432,9 @@ func DeleteProxyEndpoint(w http.ResponseWriter, r *http.Request) { uptimeMonitor.CleanRecords() } + //Update uptime monitor + UpdateUptimeMonitorTargets() + utils.SendOK(w) } @@ -751,11 +769,11 @@ func HandleUpdateHttpsRedirect(w http.ResponseWriter, r *http.Request) { } if useRedirect == "true" { sysdb.Write("settings", "redirect", true) - log.Println("Updating force HTTPS redirection to true") + SystemWideLogger.Println("Updating force HTTPS redirection to true") dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(true) } else if useRedirect == "false" { sysdb.Write("settings", "redirect", false) - log.Println("Updating force HTTPS redirection to false") + SystemWideLogger.Println("Updating force HTTPS redirection to false") dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(false) } diff --git a/src/start.go b/src/start.go index 6d210cb..c7da3b7 100644 --- a/src/start.go +++ b/src/start.go @@ -14,6 +14,7 @@ import ( "imuslab.com/zoraxy/mod/dynamicproxy/redirection" "imuslab.com/zoraxy/mod/ganserv" "imuslab.com/zoraxy/mod/geodb" + "imuslab.com/zoraxy/mod/info/logger" "imuslab.com/zoraxy/mod/mdns" "imuslab.com/zoraxy/mod/netstat" "imuslab.com/zoraxy/mod/pathrule" @@ -93,10 +94,17 @@ func startupSequence() { panic(err) } + //Create a system wide logger + l, err := logger.NewLogger("zr", "./log", *logOutputToFile) + if err == nil { + SystemWideLogger = l + } else { + panic(err) + } //Create a netstat buffer netstatBuffers, err = netstat.NewNetStatBuffer(300) if err != nil { - log.Println("Failed to load network statistic info") + SystemWideLogger.PrintAndLog("Network", "Failed to load network statistic info", err) panic(err) } @@ -134,13 +142,13 @@ func startupSequence() { BuildVersion: version, }, "") if err != nil { - log.Println("Unable to startup mDNS service. Disabling mDNS services") + SystemWideLogger.Println("Unable to startup mDNS service. Disabling mDNS services") } else { //Start initial scanning go func() { hosts := mdnsScanner.Scan(30, "") previousmdnsScanResults = hosts - log.Println("mDNS Startup scan completed") + SystemWideLogger.Println("mDNS Startup scan completed") }() //Create a ticker to update mDNS results every 5 minutes @@ -154,7 +162,7 @@ func startupSequence() { case <-ticker.C: hosts := mdnsScanner.Scan(30, "") previousmdnsScanResults = hosts - log.Println("mDNS scan result updated") + SystemWideLogger.Println("mDNS scan result updated") } } }() @@ -171,7 +179,7 @@ func startupSequence() { if usingZtAuthToken == "" { usingZtAuthToken, err = ganserv.TryLoadorAskUserForAuthkey() if err != nil { - log.Println("Failed to load ZeroTier controller API authtoken") + SystemWideLogger.Println("Failed to load ZeroTier controller API authtoken") } } ganManager = ganserv.NewNetworkManager(&ganserv.NetworkManagerOptions{ diff --git a/src/web/components/rproot.html b/src/web/components/rproot.html index 57ababf..a1ed65a 100644 --- a/src/web/components/rproot.html +++ b/src/web/components/rproot.html @@ -112,8 +112,10 @@ isUsingStaticWebServerAsRoot(function(isUsingWebServ){ if (isUsingWebServ){ $(".webservRootDisabled").addClass("disabled"); + $("#useStaticWebServer").parent().checkbox("set checked"); }else{ $(".webservRootDisabled").removeClass("disabled"); + $("#useStaticWebServer").parent().checkbox("set unchecked"); } }) } diff --git a/src/web/components/rules.html b/src/web/components/rules.html index 194ea7e..4e9bfb3 100644 --- a/src/web/components/rules.html +++ b/src/web/components/rules.html @@ -47,6 +47,12 @@
+
+
+ + +
+
@@ -123,6 +129,7 @@ var proxyDomain = $("#proxyDomain").val(); var useTLS = $("#reqTls")[0].checked; var skipTLSValidation = $("#skipTLSValidation")[0].checked; + var bypassGlobalTLS = $("#bypassGlobalTLS")[0].checked; var requireBasicAuth = $("#requireBasicAuth")[0].checked; if (type === "vdir") { @@ -162,6 +169,7 @@ tls: useTLS, ep: proxyDomain, tlsval: skipTLSValidation, + bypassGlobalTLS: bypassGlobalTLS, bauth: requireBasicAuth, cred: JSON.stringify(credentials), }, diff --git a/src/web/components/uptime.html b/src/web/components/uptime.html index f5492f0..761e4ab 100644 --- a/src/web/components/uptime.html +++ b/src/web/components/uptime.html @@ -86,7 +86,7 @@ let id = value[0].ID; let name = value[0].Name; - let url = value[0].URL; + let url = value[value.length - 1].URL; let protocol = value[0].Protocol; //Generate the status dot @@ -112,6 +112,9 @@ if (thisStatus.StatusCode >= 500 && thisStatus.StatusCode < 600){ //Special type of error, cause by downstream reverse proxy dotType = "error"; + }else if (thisStatus.StatusCode == 401){ + //Unauthorized error + dotType = "error"; }else{ dotType = "offline"; } @@ -141,6 +144,28 @@ currentOnlineStatus = ` Misconfigured`; onlineStatusCss = `color: #f38020;`; reminderEle = `Downstream proxy server is online with misconfigured settings`; + }else if (value[value.length - 1].StatusCode >= 400 && value[value.length - 1].StatusCode <= 405){ + switch(value[value.length - 1].StatusCode){ + case 400: + currentOnlineStatus = ` Bad Request`; + break; + case 401: + currentOnlineStatus = ` Unauthorized`; + break; + case 403: + currentOnlineStatus = ` Forbidden`; + break; + case 404: + currentOnlineStatus = ` Not Found`; + break; + case 405: + currentOnlineStatus = ` Method Not Allowed`; + break; + } + + onlineStatusCss = `color: #f38020;`; + reminderEle = `Target online but not accessible`; + }else{ currentOnlineStatus = ` Offline`; onlineStatusCss = `color: #df484a;`; diff --git a/src/wrappers.go b/src/wrappers.go index f3d6fde..9fd7531 100644 --- a/src/wrappers.go +++ b/src/wrappers.go @@ -19,7 +19,6 @@ package main import ( "encoding/json" "fmt" - "log" "net/http" "strings" "time" @@ -104,7 +103,21 @@ func HandleCountryDistrSummary(w http.ResponseWriter, r *http.Request) { /* Up Time Monitor */ -//Generate uptime monitor targets from reverse proxy rules + +// 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) + go func() { + uptimeMonitor.ExecuteUptimeCheck() + }() + + SystemWideLogger.PrintAndLog("Uptime", "Uptime monitor config updated", nil) + } +} + +// Generate uptime monitor targets from reverse proxy rules func GetUptimeTargetsFromReverseProxyRules(dp *dynamicproxy.Router) []*uptime.Target { subds := dp.GetSDProxyEndpointsAsMap() vdirs := dp.GetVDProxyEndpointsAsMap() @@ -263,7 +276,7 @@ func HandleWakeOnLan(w http.ResponseWriter, r *http.Request) { return } - log.Println("[WoL] Sending Wake on LAN magic packet to " + wake) + SystemWideLogger.PrintAndLog("WoL", "Sending Wake on LAN magic packet to "+wake, nil) err := wakeonlan.WakeTarget(wake) if err != nil { utils.SendErrorResponse(w, err.Error()) From ce4ce72820271a41c947ec62440e0693e349084d Mon Sep 17 00:00:00 2001 From: Toby Chui Date: Sat, 25 Nov 2023 15:54:28 +0800 Subject: [PATCH 4/6] Added optional TLS bypass mechanism + Added opt-out for subdomains for global TLS settings #44 + Optimized subdomain / vdir editing interface --- src/api.go | 1 + src/mod/dynamicproxy/dynamicproxy.go | 56 +++++++++++++++++++++++--- src/mod/dynamicproxy/typedef.go | 1 + src/reverseproxy.go | 50 ++++++++++++++++++++++- src/web/components/rules.html | 59 +++++++++++++++++++--------- src/web/components/status.html | 54 ++++++++++++++++++++++--- src/web/components/subd.html | 14 ++----- src/web/components/vdir.html | 5 ++- 8 files changed, 199 insertions(+), 41 deletions(-) diff --git a/src/api.go b/src/api.go index 5b52342..5831564 100644 --- a/src/api.go +++ b/src/api.go @@ -54,6 +54,7 @@ func initAPIs() { authRouter.HandleFunc("/api/proxy/tlscheck", HandleCheckSiteSupportTLS) authRouter.HandleFunc("/api/proxy/setIncoming", HandleIncomingPortSet) authRouter.HandleFunc("/api/proxy/useHttpsRedirect", HandleUpdateHttpsRedirect) + authRouter.HandleFunc("/api/proxy/listenPort80", HandleUpdatePort80Listener) authRouter.HandleFunc("/api/proxy/requestIsProxied", HandleManagementProxyCheck) //Reverse proxy root related APIs authRouter.HandleFunc("/api/proxy/root/listOptions", HandleRootRouteOptionList) diff --git a/src/mod/dynamicproxy/dynamicproxy.go b/src/mod/dynamicproxy/dynamicproxy.go index 4c280ea..d5f5d07 100644 --- a/src/mod/dynamicproxy/dynamicproxy.go +++ b/src/mod/dynamicproxy/dynamicproxy.go @@ -60,6 +60,12 @@ func (router *Router) UpdateTLSVersion(requireLatest bool) { router.Restart() } +// Update port 80 listener state +func (router *Router) UpdatePort80ListenerState(useRedirect bool) { + router.Option.ListenOnPort80 = useRedirect + router.Restart() +} + // Update https redirect, which will require updates func (router *Router) UpdateHttpToHttpsRedirectSetting(useRedirect bool) { router.Option.ForceHttpsRedirect = useRedirect @@ -112,16 +118,56 @@ func (router *Router) StartProxyService() error { } router.Running = true - if router.Option.Port != 80 && router.Option.ForceHttpsRedirect { + if router.Option.Port != 80 && router.Option.ListenOnPort80 { //Add a 80 to 443 redirector httpServer := &http.Server{ Addr: ":80", Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - protocol := "https://" - if router.Option.Port == 443 { - http.Redirect(w, r, protocol+r.Host+r.RequestURI, http.StatusTemporaryRedirect) + //Check if the domain requesting allow non TLS mode + domainOnly := r.Host + if strings.Contains(r.Host, ":") { + hostPath := strings.Split(r.Host, ":") + domainOnly = hostPath[0] + } + sep := router.getSubdomainProxyEndpointFromHostname(domainOnly) + if sep != nil && sep.BypassGlobalTLS { + //Allow routing via non-TLS handler + originalHostHeader := r.Host + if r.URL != nil { + r.Host = r.URL.Host + } else { + //Fallback when the upstream proxy screw something up in the header + r.URL, _ = url.Parse(originalHostHeader) + } + + sep.Proxy.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{ + ProxyDomain: sep.Domain, + OriginalHost: originalHostHeader, + UseTLS: sep.RequireTLS, + PathPrefix: "", + }) + return + } + + if router.Option.ForceHttpsRedirect { + //Redirect to https is enabled + protocol := "https://" + if router.Option.Port == 443 { + http.Redirect(w, r, protocol+r.Host+r.RequestURI, http.StatusTemporaryRedirect) + } else { + http.Redirect(w, r, protocol+r.Host+":"+strconv.Itoa(router.Option.Port)+r.RequestURI, http.StatusTemporaryRedirect) + } } else { - http.Redirect(w, r, protocol+r.Host+":"+strconv.Itoa(router.Option.Port)+r.RequestURI, http.StatusTemporaryRedirect) + //Do not do redirection + if sep != nil { + //Sub-domain exists but not allow non-TLS access + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("400 - Bad Request")) + } else { + //No defined sub-domain + http.NotFound(w, r) + } + } }), diff --git a/src/mod/dynamicproxy/typedef.go b/src/mod/dynamicproxy/typedef.go index 2372f04..43c5fa2 100644 --- a/src/mod/dynamicproxy/typedef.go +++ b/src/mod/dynamicproxy/typedef.go @@ -27,6 +27,7 @@ type RouterOption struct { Port int //Incoming port UseTls bool //Use TLS to serve incoming requsts ForceTLSLatest bool //Force TLS1.2 or above + ListenOnPort80 bool //Enable port 80 http listener ForceHttpsRedirect bool //Force redirection of http to https endpoint TlsManager *tlscert.Manager RedirectRuleTable *redirection.RuleTable diff --git a/src/reverseproxy.go b/src/reverseproxy.go index 16196a9..f1bd381 100644 --- a/src/reverseproxy.go +++ b/src/reverseproxy.go @@ -45,10 +45,20 @@ func ReverseProxtInit() { SystemWideLogger.Println("Force latest TLS mode disabled. Minimum TLS version is set to v1.0") } + listenOnPort80 := false + sysdb.Read("settings", "listenP80", &listenOnPort80) + if listenOnPort80 { + SystemWideLogger.Println("Port 80 listener enabled") + } else { + SystemWideLogger.Println("Port 80 listener disabled") + } + forceHttpsRedirect := false sysdb.Read("settings", "redirect", &forceHttpsRedirect) if forceHttpsRedirect { SystemWideLogger.Println("Force HTTPS mode enabled") + //Port 80 listener must be enabled to perform http -> https redirect + listenOnPort80 = true } else { SystemWideLogger.Println("Force HTTPS mode disabled") } @@ -58,6 +68,7 @@ func ReverseProxtInit() { Port: inboundPort, UseTls: useTls, ForceTLSLatest: forceLatestTLSVersion, + ListenOnPort80: listenOnPort80, ForceHttpsRedirect: forceHttpsRedirect, TlsManager: tlsCertManager, RedirectRuleTable: redirectTable, @@ -343,9 +354,15 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) { if stv == "" { stv = "false" } - skipTlsValidation := (stv == "true") + //Load bypass TLS option + bpgtls, _ := utils.PostPara(r, "bpgtls") + if bpgtls == "" { + bpgtls = "false" + } + bypassGlobalTLS := (bpgtls == "true") + rba, _ := utils.PostPara(r, "bauth") if rba == "" { rba = "false" @@ -365,6 +382,7 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) { RootName: targetProxyEntry.RootOrMatchingDomain, Domain: endpoint, RequireTLS: useTLS, + BypassGlobalTLS: false, SkipCertValidations: skipTlsValidation, RequireBasicAuth: requireBasicAuth, BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials, @@ -377,6 +395,7 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) { MatchingDomain: targetProxyEntry.RootOrMatchingDomain, Domain: endpoint, RequireTLS: useTLS, + BypassGlobalTLS: bypassGlobalTLS, SkipCertValidations: skipTlsValidation, RequireBasicAuth: requireBasicAuth, BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials, @@ -749,6 +768,35 @@ func ReverseProxyList(w http.ResponseWriter, r *http.Request) { } } +// Handle port 80 incoming traffics +func HandleUpdatePort80Listener(w http.ResponseWriter, r *http.Request) { + enabled, err := utils.GetPara(r, "enable") + if err != nil { + //Load the current status + currentEnabled := false + err = sysdb.Read("settings", "listenP80", ¤tEnabled) + if err != nil { + utils.SendErrorResponse(w, err.Error()) + return + } + js, _ := json.Marshal(currentEnabled) + utils.SendJSONResponse(w, string(js)) + } else { + if enabled == "true" { + sysdb.Write("settings", "listenP80", true) + SystemWideLogger.Println("Enabling port 80 listener") + dynamicProxyRouter.UpdatePort80ListenerState(true) + } else if enabled == "false" { + sysdb.Write("settings", "listenP80", false) + SystemWideLogger.Println("Disabling port 80 listener") + dynamicProxyRouter.UpdatePort80ListenerState(true) + } else { + utils.SendErrorResponse(w, "invalid mode given: "+enabled) + } + utils.SendOK(w) + } +} + // Handle https redirect func HandleUpdateHttpsRedirect(w http.ResponseWriter, r *http.Request) { useRedirect, err := utils.GetPara(r, "set") diff --git a/src/web/components/rules.html b/src/web/components/rules.html index 4e9bfb3..81f8a81 100644 --- a/src/web/components/rules.html +++ b/src/web/components/rules.html @@ -8,7 +8,7 @@