mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-06 15:47:19 +02:00
commit
20cf290d37
13
src/acme.go
13
src/acme.go
@ -4,7 +4,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -29,7 +28,7 @@ func getRandomPort(minPort int) int {
|
|||||||
|
|
||||||
// init the new ACME instance
|
// init the new ACME instance
|
||||||
func initACME() *acme.ACMEHandler {
|
func initACME() *acme.ACMEHandler {
|
||||||
log.Println("Starting ACME handler")
|
SystemWideLogger.Println("Starting ACME handler")
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
// Generate a random port above 30000
|
// Generate a random port above 30000
|
||||||
port := getRandomPort(30000)
|
port := getRandomPort(30000)
|
||||||
@ -44,7 +43,7 @@ func initACME() *acme.ACMEHandler {
|
|||||||
|
|
||||||
// create the special routing rule for ACME
|
// create the special routing rule for ACME
|
||||||
func acmeRegisterSpecialRoutingRule() {
|
func acmeRegisterSpecialRoutingRule() {
|
||||||
log.Println("Assigned temporary port:" + acmeHandler.Getport())
|
SystemWideLogger.Println("Assigned temporary port:" + acmeHandler.Getport())
|
||||||
|
|
||||||
err := dynamicProxyRouter.AddRoutingRules(&dynamicproxy.RoutingRule{
|
err := dynamicProxyRouter.AddRoutingRules(&dynamicproxy.RoutingRule{
|
||||||
ID: "acme-autorenew",
|
ID: "acme-autorenew",
|
||||||
@ -79,7 +78,7 @@ func acmeRegisterSpecialRoutingRule() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
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 {
|
if dynamicProxyRouter.Option.Port == 443 {
|
||||||
//Enable port 80 to 443 redirect
|
//Enable port 80 to 443 redirect
|
||||||
if !dynamicProxyRouter.Option.ForceHttpsRedirect {
|
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)
|
dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(true)
|
||||||
} else {
|
} else {
|
||||||
//Set this to true, so after renew, do not turn it off
|
//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 dynamicProxyRouter.Option.Port == 443 {
|
||||||
if !isForceHttpsRedirectEnabledOriginally {
|
if !isForceHttpsRedirectEnabledOriginally {
|
||||||
//Default is off. Turn the redirection off
|
//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)
|
dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,7 +129,7 @@ func HandleACMEPreferredCA(w http.ResponseWriter, r *http.Request) {
|
|||||||
acme.IsSupportedCA(ca)
|
acme.IsSupportedCA(ca)
|
||||||
//Set the new config
|
//Set the new config
|
||||||
sysdb.Write("acmepref", "prefca", ca)
|
sysdb.Write("acmepref", "prefca", ca)
|
||||||
log.Println("Updating prefered ACME CA to " + ca)
|
SystemWideLogger.Println("Updating prefered ACME CA to " + ca)
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ func initAPIs() {
|
|||||||
authRouter.HandleFunc("/api/proxy/tlscheck", HandleCheckSiteSupportTLS)
|
authRouter.HandleFunc("/api/proxy/tlscheck", HandleCheckSiteSupportTLS)
|
||||||
authRouter.HandleFunc("/api/proxy/setIncoming", HandleIncomingPortSet)
|
authRouter.HandleFunc("/api/proxy/setIncoming", HandleIncomingPortSet)
|
||||||
authRouter.HandleFunc("/api/proxy/useHttpsRedirect", HandleUpdateHttpsRedirect)
|
authRouter.HandleFunc("/api/proxy/useHttpsRedirect", HandleUpdateHttpsRedirect)
|
||||||
|
authRouter.HandleFunc("/api/proxy/listenPort80", HandleUpdatePort80Listener)
|
||||||
authRouter.HandleFunc("/api/proxy/requestIsProxied", HandleManagementProxyCheck)
|
authRouter.HandleFunc("/api/proxy/requestIsProxied", HandleManagementProxyCheck)
|
||||||
//Reverse proxy root related APIs
|
//Reverse proxy root related APIs
|
||||||
authRouter.HandleFunc("/api/proxy/root/listOptions", HandleRootRouteOptionList)
|
authRouter.HandleFunc("/api/proxy/root/listOptions", HandleRootRouteOptionList)
|
||||||
|
11
src/cert.go
11
src/cert.go
@ -6,7 +6,6 @@ import (
|
|||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -128,7 +127,7 @@ func handleListDomains(w http.ResponseWriter, r *http.Request) {
|
|||||||
certBtyes, err := os.ReadFile(certFilepath)
|
certBtyes, err := os.ReadFile(certFilepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Unable to load this file
|
// Unable to load this file
|
||||||
log.Println("Unable to load certificate: " + certFilepath)
|
SystemWideLogger.PrintAndLog("TLS", "Unable to load certificate: "+certFilepath, err)
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
// Cert loaded. Check its expiry time
|
// Cert loaded. Check its expiry time
|
||||||
@ -182,11 +181,11 @@ func handleToggleTLSProxy(w http.ResponseWriter, r *http.Request) {
|
|||||||
} else {
|
} else {
|
||||||
if newState == "true" {
|
if newState == "true" {
|
||||||
sysdb.Write("settings", "usetls", 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)
|
dynamicProxyRouter.UpdateTLSSetting(true)
|
||||||
} else if newState == "false" {
|
} else if newState == "false" {
|
||||||
sysdb.Write("settings", "usetls", 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)
|
dynamicProxyRouter.UpdateTLSSetting(false)
|
||||||
} else {
|
} else {
|
||||||
utils.SendErrorResponse(w, "invalid state given. Only support true or false")
|
utils.SendErrorResponse(w, "invalid state given. Only support true or false")
|
||||||
@ -213,11 +212,11 @@ func handleSetTlsRequireLatest(w http.ResponseWriter, r *http.Request) {
|
|||||||
} else {
|
} else {
|
||||||
if newState == "true" {
|
if newState == "true" {
|
||||||
sysdb.Write("settings", "forceLatestTLS", 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)
|
dynamicProxyRouter.UpdateTLSVersion(true)
|
||||||
} else if newState == "false" {
|
} else if newState == "false" {
|
||||||
sysdb.Write("settings", "forceLatestTLS", 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)
|
dynamicProxyRouter.UpdateTLSVersion(false)
|
||||||
} else {
|
} else {
|
||||||
utils.SendErrorResponse(w, "invalid state given")
|
utils.SendErrorResponse(w, "invalid state given")
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -29,6 +28,7 @@ type Record struct {
|
|||||||
Rootname string
|
Rootname string
|
||||||
ProxyTarget string
|
ProxyTarget string
|
||||||
UseTLS bool
|
UseTLS bool
|
||||||
|
BypassGlobalTLS bool
|
||||||
SkipTlsValidation bool
|
SkipTlsValidation bool
|
||||||
RequireBasicAuth bool
|
RequireBasicAuth bool
|
||||||
BasicAuthCredentials []*dynamicproxy.BasicAuthCredentials
|
BasicAuthCredentials []*dynamicproxy.BasicAuthCredentials
|
||||||
@ -61,11 +61,11 @@ func SaveReverseProxyEndpointToFile(proxyEndpoint *dynamicproxy.ProxyEndpoint) e
|
|||||||
func RemoveReverseProxyConfigFile(rootname string) error {
|
func RemoveReverseProxyConfigFile(rootname string) error {
|
||||||
filename := getFilenameFromRootName(rootname)
|
filename := getFilenameFromRootName(rootname)
|
||||||
removePendingFile := strings.ReplaceAll(filepath.Join("./conf/proxy/", filename), "\\", "/")
|
removePendingFile := strings.ReplaceAll(filepath.Join("./conf/proxy/", filename), "\\", "/")
|
||||||
log.Println("Config Removed: ", removePendingFile)
|
SystemWideLogger.Println("Config Removed: ", removePendingFile)
|
||||||
if utils.FileExists(removePendingFile) {
|
if utils.FileExists(removePendingFile) {
|
||||||
err := os.Remove(removePendingFile)
|
err := os.Remove(removePendingFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err.Error())
|
SystemWideLogger.PrintAndLog("Proxy", "Unabel to remove config file", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,6 +81,7 @@ func LoadReverseProxyConfig(filename string) (*Record, error) {
|
|||||||
Rootname: "",
|
Rootname: "",
|
||||||
ProxyTarget: "",
|
ProxyTarget: "",
|
||||||
UseTLS: false,
|
UseTLS: false,
|
||||||
|
BypassGlobalTLS: false,
|
||||||
SkipTlsValidation: false,
|
SkipTlsValidation: false,
|
||||||
RequireBasicAuth: false,
|
RequireBasicAuth: false,
|
||||||
BasicAuthCredentials: []*dynamicproxy.BasicAuthCredentials{},
|
BasicAuthCredentials: []*dynamicproxy.BasicAuthCredentials{},
|
||||||
@ -109,6 +110,7 @@ func ConvertProxyEndpointToRecord(targetProxyEndpoint *dynamicproxy.ProxyEndpoin
|
|||||||
Rootname: targetProxyEndpoint.RootOrMatchingDomain,
|
Rootname: targetProxyEndpoint.RootOrMatchingDomain,
|
||||||
ProxyTarget: targetProxyEndpoint.Domain,
|
ProxyTarget: targetProxyEndpoint.Domain,
|
||||||
UseTLS: targetProxyEndpoint.RequireTLS,
|
UseTLS: targetProxyEndpoint.RequireTLS,
|
||||||
|
BypassGlobalTLS: targetProxyEndpoint.BypassGlobalTLS,
|
||||||
SkipTlsValidation: targetProxyEndpoint.SkipCertValidations,
|
SkipTlsValidation: targetProxyEndpoint.SkipCertValidations,
|
||||||
RequireBasicAuth: targetProxyEndpoint.RequireBasicAuth,
|
RequireBasicAuth: targetProxyEndpoint.RequireBasicAuth,
|
||||||
BasicAuthCredentials: targetProxyEndpoint.BasicAuthCredentials,
|
BasicAuthCredentials: targetProxyEndpoint.BasicAuthCredentials,
|
||||||
@ -191,14 +193,14 @@ func ExportConfigAsZip(w http.ResponseWriter, r *http.Request) {
|
|||||||
//Also zip in the sysdb
|
//Also zip in the sysdb
|
||||||
zipFile, err := zipWriter.Create("sys.db")
|
zipFile, err := zipWriter.Create("sys.db")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("[Backup] Unable to zip sysdb: " + err.Error())
|
SystemWideLogger.PrintAndLog("Backup", "Unable to zip sysdb", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the file on disk
|
// Open the file on disk
|
||||||
file, err := os.Open("sys.db")
|
file, err := os.Open("sys.db")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("[Backup] Unable to open sysdb: " + err.Error())
|
SystemWideLogger.PrintAndLog("Backup", "Unable to open sysdb", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
@ -206,7 +208,7 @@ func ExportConfigAsZip(w http.ResponseWriter, r *http.Request) {
|
|||||||
// Copy the file contents to the zip file
|
// Copy the file contents to the zip file
|
||||||
_, err = io.Copy(zipFile, file)
|
_, err = io.Copy(zipFile, file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
SystemWideLogger.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,12 +313,12 @@ func ImportConfigFromZip(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Send a success response
|
// Send a success response
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
log.Println("Configuration restored")
|
SystemWideLogger.Println("Configuration restored")
|
||||||
fmt.Fprintln(w, "Configuration restored")
|
fmt.Fprintln(w, "Configuration restored")
|
||||||
|
|
||||||
if restoreDatabase {
|
if restoreDatabase {
|
||||||
go func() {
|
go func() {
|
||||||
log.Println("Database altered. Restarting in 3 seconds...")
|
SystemWideLogger.Println("Database altered. Restarting in 3 seconds...")
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}()
|
}()
|
||||||
|
12
src/main.go
12
src/main.go
@ -20,6 +20,7 @@ import (
|
|||||||
"imuslab.com/zoraxy/mod/email"
|
"imuslab.com/zoraxy/mod/email"
|
||||||
"imuslab.com/zoraxy/mod/ganserv"
|
"imuslab.com/zoraxy/mod/ganserv"
|
||||||
"imuslab.com/zoraxy/mod/geodb"
|
"imuslab.com/zoraxy/mod/geodb"
|
||||||
|
"imuslab.com/zoraxy/mod/info/logger"
|
||||||
"imuslab.com/zoraxy/mod/mdns"
|
"imuslab.com/zoraxy/mod/mdns"
|
||||||
"imuslab.com/zoraxy/mod/netstat"
|
"imuslab.com/zoraxy/mod/netstat"
|
||||||
"imuslab.com/zoraxy/mod/pathrule"
|
"imuslab.com/zoraxy/mod/pathrule"
|
||||||
@ -44,10 +45,11 @@ 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 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 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 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 (
|
var (
|
||||||
name = "Zoraxy"
|
name = "Zoraxy"
|
||||||
version = "2.6.7"
|
version = "2.6.8"
|
||||||
nodeUUID = "generic"
|
nodeUUID = "generic"
|
||||||
development = false //Set this to false to use embedded web fs
|
development = false //Set this to false to use embedded web fs
|
||||||
bootTime = time.Now().Unix()
|
bootTime = time.Now().Unix()
|
||||||
@ -82,6 +84,7 @@ var (
|
|||||||
//Helper modules
|
//Helper modules
|
||||||
EmailSender *email.Sender //Email sender that handle email sending
|
EmailSender *email.Sender //Email sender that handle email sending
|
||||||
AnalyticLoader *analytic.DataLoader //Data loader for Zoraxy Analytic
|
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.
|
// Kill signal handler. Do something before the system the core terminate.
|
||||||
@ -116,6 +119,9 @@ func ShutdownSeq() {
|
|||||||
fmt.Println("- Cleaning up tmp files")
|
fmt.Println("- Cleaning up tmp files")
|
||||||
os.RemoveAll("./tmp")
|
os.RemoveAll("./tmp")
|
||||||
|
|
||||||
|
fmt.Println("- Closing system wide logger")
|
||||||
|
SystemWideLogger.Close()
|
||||||
|
|
||||||
//Close database, final
|
//Close database, final
|
||||||
fmt.Println("- Stopping system database")
|
fmt.Println("- Stopping system database")
|
||||||
sysdb.Close()
|
sysdb.Close()
|
||||||
@ -151,7 +157,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
uuidBytes, err := os.ReadFile(uuidRecord)
|
uuidBytes, err := os.ReadFile(uuidRecord)
|
||||||
if err != nil {
|
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)
|
panic(err)
|
||||||
}
|
}
|
||||||
nodeUUID = string(uuidBytes)
|
nodeUUID = string(uuidBytes)
|
||||||
@ -173,7 +179,7 @@ func main() {
|
|||||||
//Start the finalize sequences
|
//Start the finalize sequences
|
||||||
finalSequence()
|
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)
|
err = http.ListenAndServe(handler.Port, nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -60,6 +60,12 @@ func (router *Router) UpdateTLSVersion(requireLatest bool) {
|
|||||||
router.Restart()
|
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
|
// Update https redirect, which will require updates
|
||||||
func (router *Router) UpdateHttpToHttpsRedirectSetting(useRedirect bool) {
|
func (router *Router) UpdateHttpToHttpsRedirectSetting(useRedirect bool) {
|
||||||
router.Option.ForceHttpsRedirect = useRedirect
|
router.Option.ForceHttpsRedirect = useRedirect
|
||||||
@ -95,6 +101,7 @@ func (router *Router) StartProxyService() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if router.Option.UseTls {
|
if router.Option.UseTls {
|
||||||
|
/*
|
||||||
//Serve with TLS mode
|
//Serve with TLS mode
|
||||||
ln, err := tls.Listen("tcp", ":"+strconv.Itoa(router.Option.Port), config)
|
ln, err := tls.Listen("tcp", ":"+strconv.Itoa(router.Option.Port), config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -103,20 +110,65 @@ func (router *Router) StartProxyService() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
router.tlsListener = ln
|
router.tlsListener = ln
|
||||||
router.server = &http.Server{Addr: ":" + strconv.Itoa(router.Option.Port), Handler: router.mux}
|
*/
|
||||||
|
router.server = &http.Server{
|
||||||
|
Addr: ":" + strconv.Itoa(router.Option.Port),
|
||||||
|
Handler: router.mux,
|
||||||
|
TLSConfig: config,
|
||||||
|
}
|
||||||
router.Running = true
|
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
|
//Add a 80 to 443 redirector
|
||||||
httpServer := &http.Server{
|
httpServer := &http.Server{
|
||||||
Addr: ":80",
|
Addr: ":80",
|
||||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
//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://"
|
protocol := "https://"
|
||||||
if router.Option.Port == 443 {
|
if router.Option.Port == 443 {
|
||||||
http.Redirect(w, r, protocol+r.Host+r.RequestURI, http.StatusTemporaryRedirect)
|
http.Redirect(w, r, protocol+r.Host+r.RequestURI, http.StatusTemporaryRedirect)
|
||||||
} else {
|
} else {
|
||||||
http.Redirect(w, r, protocol+r.Host+":"+strconv.Itoa(router.Option.Port)+r.RequestURI, http.StatusTemporaryRedirect)
|
http.Redirect(w, r, protocol+r.Host+":"+strconv.Itoa(router.Option.Port)+r.RequestURI, http.StatusTemporaryRedirect)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
//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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}),
|
}),
|
||||||
ReadTimeout: 3 * time.Second,
|
ReadTimeout: 3 * time.Second,
|
||||||
@ -143,7 +195,7 @@ func (router *Router) StartProxyService() error {
|
|||||||
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||||
//Unable to startup port 80 listener. Handle shutdown process gracefully
|
//Unable to startup port 80 listener. Handle shutdown process gracefully
|
||||||
stopChan <- true
|
stopChan <- true
|
||||||
log.Fatalf("Could not start server: %v\n", err)
|
log.Fatalf("Could not start redirection server: %v\n", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
router.tlsRedirectStop = stopChan
|
router.tlsRedirectStop = stopChan
|
||||||
@ -152,8 +204,8 @@ func (router *Router) StartProxyService() error {
|
|||||||
//Start the TLS server
|
//Start the TLS server
|
||||||
log.Println("Reverse proxy service started in the background (TLS mode)")
|
log.Println("Reverse proxy service started in the background (TLS mode)")
|
||||||
go func() {
|
go func() {
|
||||||
if err := router.server.Serve(ln); err != nil && err != http.ErrServerClosed {
|
if err := router.server.ListenAndServeTLS("", ""); err != nil && err != http.ErrServerClosed {
|
||||||
log.Fatalf("Could not start server: %v\n", err)
|
log.Fatalf("Could not start proxy server: %v\n", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
} else {
|
} else {
|
||||||
|
@ -38,6 +38,7 @@ func (router *Router) AddSubdomainRoutingService(options *SubdOptions) error {
|
|||||||
Domain: domain,
|
Domain: domain,
|
||||||
RequireTLS: options.RequireTLS,
|
RequireTLS: options.RequireTLS,
|
||||||
Proxy: proxy,
|
Proxy: proxy,
|
||||||
|
BypassGlobalTLS: options.BypassGlobalTLS,
|
||||||
SkipCertValidations: options.SkipCertValidations,
|
SkipCertValidations: options.SkipCertValidations,
|
||||||
RequireBasicAuth: options.RequireBasicAuth,
|
RequireBasicAuth: options.RequireBasicAuth,
|
||||||
BasicAuthCredentials: options.BasicAuthCredentials,
|
BasicAuthCredentials: options.BasicAuthCredentials,
|
||||||
|
@ -27,6 +27,7 @@ type RouterOption struct {
|
|||||||
Port int //Incoming port
|
Port int //Incoming port
|
||||||
UseTls bool //Use TLS to serve incoming requsts
|
UseTls bool //Use TLS to serve incoming requsts
|
||||||
ForceTLSLatest bool //Force TLS1.2 or above
|
ForceTLSLatest bool //Force TLS1.2 or above
|
||||||
|
ListenOnPort80 bool //Enable port 80 http listener
|
||||||
ForceHttpsRedirect bool //Force redirection of http to https endpoint
|
ForceHttpsRedirect bool //Force redirection of http to https endpoint
|
||||||
TlsManager *tlscert.Manager
|
TlsManager *tlscert.Manager
|
||||||
RedirectRuleTable *redirection.RuleTable
|
RedirectRuleTable *redirection.RuleTable
|
||||||
|
103
src/mod/info/logger/logger.go
Normal file
103
src/mod/info/logger/logger.go
Normal file
@ -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()
|
||||||
|
}
|
122
src/mod/info/logviewer/logviewer.go
Normal file
122
src/mod/info/logviewer/logviewer.go
Normal file
@ -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")
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
@ -25,33 +24,43 @@ func ReverseProxtInit() {
|
|||||||
inboundPort := 80
|
inboundPort := 80
|
||||||
if sysdb.KeyExists("settings", "inbound") {
|
if sysdb.KeyExists("settings", "inbound") {
|
||||||
sysdb.Read("settings", "inbound", &inboundPort)
|
sysdb.Read("settings", "inbound", &inboundPort)
|
||||||
log.Println("Serving inbound port ", inboundPort)
|
SystemWideLogger.Println("Serving inbound port ", inboundPort)
|
||||||
} else {
|
} else {
|
||||||
log.Println("Inbound port not set. Using default (80)")
|
SystemWideLogger.Println("Inbound port not set. Using default (80)")
|
||||||
}
|
}
|
||||||
|
|
||||||
useTls := false
|
useTls := false
|
||||||
sysdb.Read("settings", "usetls", &useTls)
|
sysdb.Read("settings", "usetls", &useTls)
|
||||||
if useTls {
|
if useTls {
|
||||||
log.Println("TLS mode enabled. Serving proxxy request with TLS")
|
SystemWideLogger.Println("TLS mode enabled. Serving proxxy request with TLS")
|
||||||
} else {
|
} 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
|
forceLatestTLSVersion := false
|
||||||
sysdb.Read("settings", "forceLatestTLS", &forceLatestTLSVersion)
|
sysdb.Read("settings", "forceLatestTLS", &forceLatestTLSVersion)
|
||||||
if 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 {
|
} 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")
|
||||||
|
}
|
||||||
|
|
||||||
|
listenOnPort80 := false
|
||||||
|
sysdb.Read("settings", "listenP80", &listenOnPort80)
|
||||||
|
if listenOnPort80 {
|
||||||
|
SystemWideLogger.Println("Port 80 listener enabled")
|
||||||
|
} else {
|
||||||
|
SystemWideLogger.Println("Port 80 listener disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
forceHttpsRedirect := false
|
forceHttpsRedirect := false
|
||||||
sysdb.Read("settings", "redirect", &forceHttpsRedirect)
|
sysdb.Read("settings", "redirect", &forceHttpsRedirect)
|
||||||
if forceHttpsRedirect {
|
if forceHttpsRedirect {
|
||||||
log.Println("Force HTTPS mode enabled")
|
SystemWideLogger.Println("Force HTTPS mode enabled")
|
||||||
|
//Port 80 listener must be enabled to perform http -> https redirect
|
||||||
|
listenOnPort80 = true
|
||||||
} else {
|
} else {
|
||||||
log.Println("Force HTTPS mode disabled")
|
SystemWideLogger.Println("Force HTTPS mode disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
dprouter, err := dynamicproxy.NewDynamicProxy(dynamicproxy.RouterOption{
|
dprouter, err := dynamicproxy.NewDynamicProxy(dynamicproxy.RouterOption{
|
||||||
@ -59,6 +68,7 @@ func ReverseProxtInit() {
|
|||||||
Port: inboundPort,
|
Port: inboundPort,
|
||||||
UseTls: useTls,
|
UseTls: useTls,
|
||||||
ForceTLSLatest: forceLatestTLSVersion,
|
ForceTLSLatest: forceLatestTLSVersion,
|
||||||
|
ListenOnPort80: listenOnPort80,
|
||||||
ForceHttpsRedirect: forceHttpsRedirect,
|
ForceHttpsRedirect: forceHttpsRedirect,
|
||||||
TlsManager: tlsCertManager,
|
TlsManager: tlsCertManager,
|
||||||
RedirectRuleTable: redirectTable,
|
RedirectRuleTable: redirectTable,
|
||||||
@ -67,7 +77,7 @@ func ReverseProxtInit() {
|
|||||||
WebDirectory: *staticWebServerRoot,
|
WebDirectory: *staticWebServerRoot,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err.Error())
|
SystemWideLogger.PrintAndLog("Proxy", "Unable to create dynamic proxy router", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +88,7 @@ func ReverseProxtInit() {
|
|||||||
for _, conf := range confs {
|
for _, conf := range confs {
|
||||||
record, err := LoadReverseProxyConfig(conf)
|
record, err := LoadReverseProxyConfig(conf)
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +102,7 @@ func ReverseProxtInit() {
|
|||||||
MatchingDomain: record.Rootname,
|
MatchingDomain: record.Rootname,
|
||||||
Domain: record.ProxyTarget,
|
Domain: record.ProxyTarget,
|
||||||
RequireTLS: record.UseTLS,
|
RequireTLS: record.UseTLS,
|
||||||
|
BypassGlobalTLS: record.BypassGlobalTLS,
|
||||||
SkipCertValidations: record.SkipTlsValidation,
|
SkipCertValidations: record.SkipTlsValidation,
|
||||||
RequireBasicAuth: record.RequireBasicAuth,
|
RequireBasicAuth: record.RequireBasicAuth,
|
||||||
BasicAuthCredentials: record.BasicAuthCredentials,
|
BasicAuthCredentials: record.BasicAuthCredentials,
|
||||||
@ -102,13 +113,14 @@ func ReverseProxtInit() {
|
|||||||
RootName: record.Rootname,
|
RootName: record.Rootname,
|
||||||
Domain: record.ProxyTarget,
|
Domain: record.ProxyTarget,
|
||||||
RequireTLS: record.UseTLS,
|
RequireTLS: record.UseTLS,
|
||||||
|
BypassGlobalTLS: record.BypassGlobalTLS,
|
||||||
SkipCertValidations: record.SkipTlsValidation,
|
SkipCertValidations: record.SkipTlsValidation,
|
||||||
RequireBasicAuth: record.RequireBasicAuth,
|
RequireBasicAuth: record.RequireBasicAuth,
|
||||||
BasicAuthCredentials: record.BasicAuthCredentials,
|
BasicAuthCredentials: record.BasicAuthCredentials,
|
||||||
BasicAuthExceptionRules: record.BasicAuthExceptionRules,
|
BasicAuthExceptionRules: record.BasicAuthExceptionRules,
|
||||||
})
|
})
|
||||||
} else {
|
} 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 +129,7 @@ func ReverseProxtInit() {
|
|||||||
//reverse proxy server in front of this service
|
//reverse proxy server in front of this service
|
||||||
time.Sleep(300 * time.Millisecond)
|
time.Sleep(300 * time.Millisecond)
|
||||||
dynamicProxyRouter.StartProxyService()
|
dynamicProxyRouter.StartProxyService()
|
||||||
log.Println("Dynamic Reverse Proxy service started")
|
SystemWideLogger.Println("Dynamic Reverse Proxy service started")
|
||||||
|
|
||||||
//Add all proxy services to uptime monitor
|
//Add all proxy services to uptime monitor
|
||||||
//Create a uptime monitor service
|
//Create a uptime monitor service
|
||||||
@ -128,7 +140,7 @@ func ReverseProxtInit() {
|
|||||||
Interval: 300, //5 minutes
|
Interval: 300, //5 minutes
|
||||||
MaxRecordsStore: 288, //1 day
|
MaxRecordsStore: 288, //1 day
|
||||||
})
|
})
|
||||||
log.Println("Uptime Monitor background service started")
|
SystemWideLogger.Println("Uptime Monitor background service started")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -180,6 +192,13 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
useTLS := (tls == "true")
|
useTLS := (tls == "true")
|
||||||
|
|
||||||
|
bypassGlobalTLS, _ := utils.PostPara(r, "bypassGlobalTLS")
|
||||||
|
if bypassGlobalTLS == "" {
|
||||||
|
bypassGlobalTLS = "false"
|
||||||
|
}
|
||||||
|
|
||||||
|
useBypassGlobalTLS := bypassGlobalTLS == "true"
|
||||||
|
|
||||||
stv, _ := utils.PostPara(r, "tlsval")
|
stv, _ := utils.PostPara(r, "tlsval")
|
||||||
if stv == "" {
|
if stv == "" {
|
||||||
stv = "false"
|
stv = "false"
|
||||||
@ -240,6 +259,7 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
RootName: vdir,
|
RootName: vdir,
|
||||||
Domain: endpoint,
|
Domain: endpoint,
|
||||||
RequireTLS: useTLS,
|
RequireTLS: useTLS,
|
||||||
|
BypassGlobalTLS: useBypassGlobalTLS,
|
||||||
SkipCertValidations: skipTlsValidation,
|
SkipCertValidations: skipTlsValidation,
|
||||||
RequireBasicAuth: requireBasicAuth,
|
RequireBasicAuth: requireBasicAuth,
|
||||||
BasicAuthCredentials: basicAuthCredentials,
|
BasicAuthCredentials: basicAuthCredentials,
|
||||||
@ -257,6 +277,7 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
MatchingDomain: subdomain,
|
MatchingDomain: subdomain,
|
||||||
Domain: endpoint,
|
Domain: endpoint,
|
||||||
RequireTLS: useTLS,
|
RequireTLS: useTLS,
|
||||||
|
BypassGlobalTLS: useBypassGlobalTLS,
|
||||||
SkipCertValidations: skipTlsValidation,
|
SkipCertValidations: skipTlsValidation,
|
||||||
RequireBasicAuth: requireBasicAuth,
|
RequireBasicAuth: requireBasicAuth,
|
||||||
BasicAuthCredentials: basicAuthCredentials,
|
BasicAuthCredentials: basicAuthCredentials,
|
||||||
@ -281,6 +302,7 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
Rootname: rootname,
|
Rootname: rootname,
|
||||||
ProxyTarget: endpoint,
|
ProxyTarget: endpoint,
|
||||||
UseTLS: useTLS,
|
UseTLS: useTLS,
|
||||||
|
BypassGlobalTLS: useBypassGlobalTLS,
|
||||||
SkipTlsValidation: skipTlsValidation,
|
SkipTlsValidation: skipTlsValidation,
|
||||||
RequireBasicAuth: requireBasicAuth,
|
RequireBasicAuth: requireBasicAuth,
|
||||||
BasicAuthCredentials: basicAuthCredentials,
|
BasicAuthCredentials: basicAuthCredentials,
|
||||||
@ -332,9 +354,15 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
if stv == "" {
|
if stv == "" {
|
||||||
stv = "false"
|
stv = "false"
|
||||||
}
|
}
|
||||||
|
|
||||||
skipTlsValidation := (stv == "true")
|
skipTlsValidation := (stv == "true")
|
||||||
|
|
||||||
|
//Load bypass TLS option
|
||||||
|
bpgtls, _ := utils.PostPara(r, "bpgtls")
|
||||||
|
if bpgtls == "" {
|
||||||
|
bpgtls = "false"
|
||||||
|
}
|
||||||
|
bypassGlobalTLS := (bpgtls == "true")
|
||||||
|
|
||||||
rba, _ := utils.PostPara(r, "bauth")
|
rba, _ := utils.PostPara(r, "bauth")
|
||||||
if rba == "" {
|
if rba == "" {
|
||||||
rba = "false"
|
rba = "false"
|
||||||
@ -354,6 +382,7 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
RootName: targetProxyEntry.RootOrMatchingDomain,
|
RootName: targetProxyEntry.RootOrMatchingDomain,
|
||||||
Domain: endpoint,
|
Domain: endpoint,
|
||||||
RequireTLS: useTLS,
|
RequireTLS: useTLS,
|
||||||
|
BypassGlobalTLS: false,
|
||||||
SkipCertValidations: skipTlsValidation,
|
SkipCertValidations: skipTlsValidation,
|
||||||
RequireBasicAuth: requireBasicAuth,
|
RequireBasicAuth: requireBasicAuth,
|
||||||
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
|
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
|
||||||
@ -366,6 +395,7 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
MatchingDomain: targetProxyEntry.RootOrMatchingDomain,
|
MatchingDomain: targetProxyEntry.RootOrMatchingDomain,
|
||||||
Domain: endpoint,
|
Domain: endpoint,
|
||||||
RequireTLS: useTLS,
|
RequireTLS: useTLS,
|
||||||
|
BypassGlobalTLS: bypassGlobalTLS,
|
||||||
SkipCertValidations: skipTlsValidation,
|
SkipCertValidations: skipTlsValidation,
|
||||||
RequireBasicAuth: requireBasicAuth,
|
RequireBasicAuth: requireBasicAuth,
|
||||||
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
|
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
|
||||||
@ -385,6 +415,10 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
|
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
|
||||||
}
|
}
|
||||||
SaveReverseProxyConfigToFile(&thisProxyConfigRecord)
|
SaveReverseProxyConfigToFile(&thisProxyConfigRecord)
|
||||||
|
|
||||||
|
//Update uptime monitor
|
||||||
|
UpdateUptimeMonitorTargets()
|
||||||
|
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,6 +451,9 @@ func DeleteProxyEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
uptimeMonitor.CleanRecords()
|
uptimeMonitor.CleanRecords()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Update uptime monitor
|
||||||
|
UpdateUptimeMonitorTargets()
|
||||||
|
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -731,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
|
// Handle https redirect
|
||||||
func HandleUpdateHttpsRedirect(w http.ResponseWriter, r *http.Request) {
|
func HandleUpdateHttpsRedirect(w http.ResponseWriter, r *http.Request) {
|
||||||
useRedirect, err := utils.GetPara(r, "set")
|
useRedirect, err := utils.GetPara(r, "set")
|
||||||
@ -751,11 +817,11 @@ func HandleUpdateHttpsRedirect(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
if useRedirect == "true" {
|
if useRedirect == "true" {
|
||||||
sysdb.Write("settings", "redirect", 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)
|
dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(true)
|
||||||
} else if useRedirect == "false" {
|
} else if useRedirect == "false" {
|
||||||
sysdb.Write("settings", "redirect", 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)
|
dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
src/start.go
20
src/start.go
@ -14,6 +14,7 @@ import (
|
|||||||
"imuslab.com/zoraxy/mod/dynamicproxy/redirection"
|
"imuslab.com/zoraxy/mod/dynamicproxy/redirection"
|
||||||
"imuslab.com/zoraxy/mod/ganserv"
|
"imuslab.com/zoraxy/mod/ganserv"
|
||||||
"imuslab.com/zoraxy/mod/geodb"
|
"imuslab.com/zoraxy/mod/geodb"
|
||||||
|
"imuslab.com/zoraxy/mod/info/logger"
|
||||||
"imuslab.com/zoraxy/mod/mdns"
|
"imuslab.com/zoraxy/mod/mdns"
|
||||||
"imuslab.com/zoraxy/mod/netstat"
|
"imuslab.com/zoraxy/mod/netstat"
|
||||||
"imuslab.com/zoraxy/mod/pathrule"
|
"imuslab.com/zoraxy/mod/pathrule"
|
||||||
@ -93,10 +94,17 @@ func startupSequence() {
|
|||||||
panic(err)
|
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
|
//Create a netstat buffer
|
||||||
netstatBuffers, err = netstat.NewNetStatBuffer(300)
|
netstatBuffers, err = netstat.NewNetStatBuffer(300)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Failed to load network statistic info")
|
SystemWideLogger.PrintAndLog("Network", "Failed to load network statistic info", err)
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,13 +142,13 @@ func startupSequence() {
|
|||||||
BuildVersion: version,
|
BuildVersion: version,
|
||||||
}, "")
|
}, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.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(30, "")
|
||||||
previousmdnsScanResults = hosts
|
previousmdnsScanResults = hosts
|
||||||
log.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
|
||||||
@ -154,7 +162,7 @@ func startupSequence() {
|
|||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
hosts := mdnsScanner.Scan(30, "")
|
hosts := mdnsScanner.Scan(30, "")
|
||||||
previousmdnsScanResults = hosts
|
previousmdnsScanResults = hosts
|
||||||
log.Println("mDNS scan result updated")
|
SystemWideLogger.Println("mDNS scan result updated")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -171,7 +179,7 @@ func startupSequence() {
|
|||||||
if usingZtAuthToken == "" {
|
if usingZtAuthToken == "" {
|
||||||
usingZtAuthToken, err = ganserv.TryLoadorAskUserForAuthkey()
|
usingZtAuthToken, err = ganserv.TryLoadorAskUserForAuthkey()
|
||||||
if err != nil {
|
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{
|
ganManager = ganserv.NewNetworkManager(&ganserv.NetworkManagerOptions{
|
||||||
@ -220,7 +228,7 @@ func startupSequence() {
|
|||||||
|
|
||||||
staticWebServer = webserv.NewWebServer(&webserv.WebServerOptions{
|
staticWebServer = webserv.NewWebServer(&webserv.WebServerOptions{
|
||||||
Sysdb: sysdb,
|
Sysdb: sysdb,
|
||||||
Port: "8081", //Default Port
|
Port: "5487", //Default Port
|
||||||
WebRoot: *staticWebServerRoot,
|
WebRoot: *staticWebServerRoot,
|
||||||
EnableDirectoryListing: true,
|
EnableDirectoryListing: true,
|
||||||
EnableWebDirManager: *allowWebFileManager,
|
EnableWebDirManager: *allowWebFileManager,
|
||||||
|
@ -75,13 +75,13 @@
|
|||||||
$("#rootReqTLS").parent().addClass("disabled");
|
$("#rootReqTLS").parent().addClass("disabled");
|
||||||
|
|
||||||
//Check if web server is enabled. If not, ask if the user want to enable it
|
//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){
|
confirmBox("Enable static web server now?", function(choice){
|
||||||
if (choice == true){
|
if (choice == true){
|
||||||
$("#webserv_enable").parent().checkbox("set checked");
|
$("#webserv_enable").parent().checkbox("set checked");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}*/
|
||||||
}else{
|
}else{
|
||||||
$("#rootReqTLS").parent().removeClass("disabled");
|
$("#rootReqTLS").parent().removeClass("disabled");
|
||||||
$("#proxyRoot").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){
|
$.get("/api/proxy/list?type=root", function(data){
|
||||||
if (data == null){
|
if (data == null){
|
||||||
|
|
||||||
@ -97,10 +97,39 @@
|
|||||||
$("#proxyRoot").val(data.Domain);
|
$("#proxyRoot").val(data.Domain);
|
||||||
checkRootRequireTLS(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");
|
||||||
|
$("#useStaticWebServer").parent().checkbox("set checked");
|
||||||
|
}else{
|
||||||
|
$(".webservRootDisabled").removeClass("disabled");
|
||||||
|
$("#useStaticWebServer").parent().checkbox("set unchecked");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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(){
|
function updateRootSettingStates(){
|
||||||
$.get("/api/cert/tls", function(data){
|
$.get("/api/cert/tls", function(data){
|
||||||
@ -111,6 +140,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Bind event to tab switch
|
//Bind event to tab switch
|
||||||
tabSwitchEventBind["setroot"] = function(){
|
tabSwitchEventBind["setroot"] = function(){
|
||||||
//On switch over to this page, update root info
|
//On switch over to this page, update root info
|
||||||
@ -137,11 +167,12 @@
|
|||||||
let useRedirect = $("#unsetRedirect")[0].checked;
|
let useRedirect = $("#unsetRedirect")[0].checked;
|
||||||
updateRedirectionDomainSettingInputBox(useRedirect);
|
updateRedirectionDomainSettingInputBox(useRedirect);
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
checkCustomRedirectForUnsetSubd();
|
checkCustomRedirectForUnsetSubd();
|
||||||
|
|
||||||
|
//Check if the given domain will redirect to https
|
||||||
function checkRootRequireTLS(targetDomain){
|
function checkRootRequireTLS(targetDomain){
|
||||||
//Trim off the http or https from the origin
|
//Trim off the http or https from the origin
|
||||||
if (targetDomain.startsWith("http://")){
|
if (targetDomain.startsWith("http://")){
|
||||||
@ -168,7 +199,7 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Set the new proxy root option
|
||||||
function setProxyRoot(){
|
function setProxyRoot(){
|
||||||
var newpr = $("#proxyRoot").val();
|
var newpr = $("#proxyRoot").val();
|
||||||
if (newpr.trim() == ""){
|
if (newpr.trim() == ""){
|
||||||
@ -189,8 +220,24 @@
|
|||||||
msgbox(data.error, false, 5000);
|
msgbox(data.error, false, 5000);
|
||||||
}else{
|
}else{
|
||||||
//OK
|
//OK
|
||||||
initRootInfo();
|
initRootInfo(function(){
|
||||||
msgbox("Proxy Root Updated")
|
//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);
|
||||||
|
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Proxy Type</label>
|
<label>Proxy Type</label>
|
||||||
<div class="ui selection dropdown">
|
<div class="ui selection dropdown">
|
||||||
<input type="hidden" id="ptype" value="subd">
|
<input type="hidden" id="ptype" value="subd" onchange="handleProxyTypeOptionChange(this.value)">
|
||||||
<i class="dropdown icon"></i>
|
<i class="dropdown icon"></i>
|
||||||
<div class="default text">Proxy Type</div>
|
<div class="default text">Proxy Type</div>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
@ -22,7 +22,7 @@
|
|||||||
<input type="text" id="rootname" placeholder="s1.mydomain.com">
|
<input type="text" id="rootname" placeholder="s1.mydomain.com">
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>IP Address or Domain Name with port</label>
|
<label>Target IP Address or Domain Name with port</label>
|
||||||
<input type="text" id="proxyDomain" onchange="autoCheckTls(this.value);">
|
<input type="text" id="proxyDomain" onchange="autoCheckTls(this.value);">
|
||||||
<small>E.g. 192.168.0.101:8000 or example.com</small>
|
<small>E.g. 192.168.0.101:8000 or example.com</small>
|
||||||
</div>
|
</div>
|
||||||
@ -44,7 +44,13 @@
|
|||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" id="skipTLSValidation">
|
<input type="checkbox" id="skipTLSValidation">
|
||||||
<label>Ignore TLS/SSL Verification Error<br><small>E.g. self-signed, expired certificate (Not Recommended)</small></label>
|
<label>Ignore TLS/SSL Verification Error<br><small>For targets that is using self-signed, expired certificate (Not Recommended)</small></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" id="bypassGlobalTLS">
|
||||||
|
<label>Allow plain HTTP access<br><small>Allow this subdomain to be connected without TLS (Require HTTP server enabled on port 80)</small></label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
@ -123,6 +129,7 @@
|
|||||||
var proxyDomain = $("#proxyDomain").val();
|
var proxyDomain = $("#proxyDomain").val();
|
||||||
var useTLS = $("#reqTls")[0].checked;
|
var useTLS = $("#reqTls")[0].checked;
|
||||||
var skipTLSValidation = $("#skipTLSValidation")[0].checked;
|
var skipTLSValidation = $("#skipTLSValidation")[0].checked;
|
||||||
|
var bypassGlobalTLS = $("#bypassGlobalTLS")[0].checked;
|
||||||
var requireBasicAuth = $("#requireBasicAuth")[0].checked;
|
var requireBasicAuth = $("#requireBasicAuth")[0].checked;
|
||||||
|
|
||||||
if (type === "vdir") {
|
if (type === "vdir") {
|
||||||
@ -162,6 +169,7 @@
|
|||||||
tls: useTLS,
|
tls: useTLS,
|
||||||
ep: proxyDomain,
|
ep: proxyDomain,
|
||||||
tlsval: skipTLSValidation,
|
tlsval: skipTLSValidation,
|
||||||
|
bypassGlobalTLS: bypassGlobalTLS,
|
||||||
bauth: requireBasicAuth,
|
bauth: requireBasicAuth,
|
||||||
cred: JSON.stringify(credentials),
|
cred: JSON.stringify(credentials),
|
||||||
},
|
},
|
||||||
@ -206,6 +214,14 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleProxyTypeOptionChange(newType){
|
||||||
|
if (newType == "subd"){
|
||||||
|
$("#bypassGlobalTLS").parent().removeClass("disabled");
|
||||||
|
}else if (newType == "vdir"){
|
||||||
|
$("#bypassGlobalTLS").parent().addClass("disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Generic functions for delete rp endpoints
|
//Generic functions for delete rp endpoints
|
||||||
function deleteEndpoint(ptype, epoint){
|
function deleteEndpoint(ptype, epoint){
|
||||||
if (confirm("Confirm remove proxy for :" + epoint + " (type: " + ptype + ")?")){
|
if (confirm("Confirm remove proxy for :" + epoint + " (type: " + ptype + ")?")){
|
||||||
@ -331,7 +347,7 @@
|
|||||||
var columns = row.find('td[data-label]');
|
var columns = row.find('td[data-label]');
|
||||||
var payload = $(row).attr("payload");
|
var payload = $(row).attr("payload");
|
||||||
payload = JSON.parse(decodeURIComponent(payload));
|
payload = JSON.parse(decodeURIComponent(payload));
|
||||||
|
console.log(payload);
|
||||||
//console.log(payload);
|
//console.log(payload);
|
||||||
columns.each(function(index) {
|
columns.each(function(index) {
|
||||||
var column = $(this);
|
var column = $(this);
|
||||||
@ -347,34 +363,37 @@
|
|||||||
var datatype = $(this).attr("datatype");
|
var datatype = $(this).attr("datatype");
|
||||||
if (datatype == "domain"){
|
if (datatype == "domain"){
|
||||||
let domain = payload.Domain;
|
let domain = payload.Domain;
|
||||||
|
//Target require TLS for proxying
|
||||||
let tls = payload.RequireTLS;
|
let tls = payload.RequireTLS;
|
||||||
if (tls){
|
if (tls){
|
||||||
tls = "checked";
|
tls = "checked";
|
||||||
}else{
|
}else{
|
||||||
tls = "";
|
tls = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Require TLS validation
|
||||||
|
let skipTLSValidation = payload.SkipCertValidations;
|
||||||
|
let checkstate = "";
|
||||||
|
if (skipTLSValidation){
|
||||||
|
checkstate = "checked";
|
||||||
|
}
|
||||||
|
|
||||||
input = `
|
input = `
|
||||||
<div class="ui mini fluid input">
|
<div class="ui mini fluid input">
|
||||||
<input type="text" class="Domain" value="${domain}">
|
<input type="text" class="Domain" value="${domain}">
|
||||||
</div>
|
</div>
|
||||||
<div class="ui checkbox" style="margin-top: 0.4em;">
|
<div class="ui checkbox" style="margin-top: 0.4em;">
|
||||||
<input type="checkbox" class="RequireTLS" ${tls}>
|
<input type="checkbox" class="RequireTLS" ${tls}>
|
||||||
<label>Require TLS</label>
|
<label>Require TLS<br>
|
||||||
|
<small>Proxy target require HTTPS connection</small></label>
|
||||||
|
</div><br>
|
||||||
|
<div class="ui checkbox" style="margin-top: 0.4em;">
|
||||||
|
<input type="checkbox" class="SkipCertValidations" ${checkstate}>
|
||||||
|
<label>Skip Verification<br>
|
||||||
|
<small>Check this if proxy target is using self signed certificates</small></label>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
column.empty().append(input);
|
column.empty().append(input);
|
||||||
|
|
||||||
}else if (datatype == "skipver"){
|
|
||||||
let skipTLSValidation = payload.SkipCertValidations;
|
|
||||||
let checkstate = "";
|
|
||||||
if (skipTLSValidation){
|
|
||||||
checkstate = "checked";
|
|
||||||
}
|
|
||||||
column.empty().append(`<div class="ui checkbox" style="margin-top: 0.4em;">
|
|
||||||
<input type="checkbox" class="SkipCertValidations" ${checkstate}>
|
|
||||||
<label>Skip Verification</label>
|
|
||||||
<small>Check this if you are using self signed certificates</small>
|
|
||||||
</div>`);
|
|
||||||
}else if (datatype == "basicauth"){
|
}else if (datatype == "basicauth"){
|
||||||
let requireBasicAuth = payload.RequireBasicAuth;
|
let requireBasicAuth = payload.RequireBasicAuth;
|
||||||
let checkstate = "";
|
let checkstate = "";
|
||||||
@ -392,6 +411,16 @@
|
|||||||
<button title="Cancel" onclick="exitProxyInlineEdit('${endpointType}');" class="ui basic small circular icon button"><i class="ui remove icon"></i></button>
|
<button title="Cancel" onclick="exitProxyInlineEdit('${endpointType}');" class="ui basic small circular icon button"><i class="ui remove icon"></i></button>
|
||||||
<button title="Save" onclick="saveProxyInlineEdit('${uuid}');" class="ui basic small circular icon button"><i class="ui green save icon"></i></button>
|
<button title="Save" onclick="saveProxyInlineEdit('${uuid}');" class="ui basic small circular icon button"><i class="ui green save icon"></i></button>
|
||||||
`);
|
`);
|
||||||
|
}else if (datatype == "inbound" && payload.ProxyType == 0){
|
||||||
|
let originalContent = $(column).html();
|
||||||
|
column.empty().append(`${originalContent}
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<div class="ui checkbox" style="margin-top: 0.4em;">
|
||||||
|
<input type="checkbox" class="BypassGlobalTLS" ${payload.BypassGlobalTLS?"checked":""}>
|
||||||
|
<label>Allow plain HTTP access<br>
|
||||||
|
<small>Allow inbound connections without TLS/SSL</small></label>
|
||||||
|
</div><br>
|
||||||
|
`);
|
||||||
}else{
|
}else{
|
||||||
//Unknown field. Leave it untouched
|
//Unknown field. Leave it untouched
|
||||||
}
|
}
|
||||||
@ -423,6 +452,7 @@
|
|||||||
let requireTLS = $(row).find(".RequireTLS")[0].checked;
|
let requireTLS = $(row).find(".RequireTLS")[0].checked;
|
||||||
let skipCertValidations = $(row).find(".SkipCertValidations")[0].checked;
|
let skipCertValidations = $(row).find(".SkipCertValidations")[0].checked;
|
||||||
let requireBasicAuth = $(row).find(".RequireBasicAuth")[0].checked;
|
let requireBasicAuth = $(row).find(".RequireBasicAuth")[0].checked;
|
||||||
|
let bypassGlobalTLS = $(row).find(".BypassGlobalTLS")[0].checked;
|
||||||
|
|
||||||
console.log(newDomain, requireTLS, skipCertValidations, requireBasicAuth)
|
console.log(newDomain, requireTLS, skipCertValidations, requireBasicAuth)
|
||||||
|
|
||||||
@ -433,6 +463,7 @@
|
|||||||
"type": epttype,
|
"type": epttype,
|
||||||
"rootname": uuid,
|
"rootname": uuid,
|
||||||
"ep":newDomain,
|
"ep":newDomain,
|
||||||
|
"bpgtls": bypassGlobalTLS,
|
||||||
"tls" :requireTLS,
|
"tls" :requireTLS,
|
||||||
"tlsval": skipCertValidations,
|
"tlsval": skipCertValidations,
|
||||||
"bauth" :requireBasicAuth,
|
"bauth" :requireBasicAuth,
|
||||||
|
@ -72,10 +72,15 @@
|
|||||||
<label>Use TLS to serve proxy request</label>
|
<label>Use TLS to serve proxy request</label>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<div id="redirect" class="ui toggle notloopbackOnly tlsEnabledOnly checkbox" style="margin-top: 0.6em;">
|
<div id="listenP80" class="ui toggle notloopbackOnly tlsEnabledOnly checkbox" style="margin-top: 0.6em;" >
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<label>Force redirect HTTP request to HTTPS<br>
|
<label>Enable HTTP server on port 80<br>
|
||||||
<small>(Only apply when listening port is not 80)</small></label>
|
<small>(Only apply when TLS enabled and not using port 80)</small></label>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div id="redirect" class="ui toggle notloopbackOnly tlsEnabledOnly checkbox" style="margin-top: 0.6em; padding-left: 2em;">
|
||||||
|
<input type="checkbox">
|
||||||
|
<label>Force redirect HTTP request to HTTPS</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
|
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
|
||||||
<div class="ui accordion advanceSettings">
|
<div class="ui accordion advanceSettings">
|
||||||
@ -181,6 +186,7 @@
|
|||||||
$("#serverstatus").removeClass("green");
|
$("#serverstatus").removeClass("green");
|
||||||
}
|
}
|
||||||
$("#incomingPort").val(data.Option.Port);
|
$("#incomingPort").val(data.Option.Port);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -305,6 +311,27 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleP80ListenerStateChange(enabled){
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/proxy/listenPort80",
|
||||||
|
data: {"enable": enabled},
|
||||||
|
success: function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
console.log(data.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (enabled){
|
||||||
|
$("#redirect").show();
|
||||||
|
msgbox("Port 80 listener enabled");
|
||||||
|
}else{
|
||||||
|
$("#redirect").hide();
|
||||||
|
msgbox("Port 80 listener disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function handlePortChange(){
|
function handlePortChange(){
|
||||||
var newPortValue = $("#incomingPort").val();
|
var newPortValue = $("#incomingPort").val();
|
||||||
@ -323,6 +350,25 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initPort80ListenerSetting(){
|
||||||
|
$.get("/api/proxy/listenPort80", function(data){
|
||||||
|
if (data){
|
||||||
|
$("#listenP80").checkbox("set checked");
|
||||||
|
$("#redirect").show();
|
||||||
|
}else{
|
||||||
|
$("#listenP80").checkbox("set unchecked");
|
||||||
|
$("#redirect").hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#listenP80").find("input").on("change", function(){
|
||||||
|
let enabled = $(this)[0].checked;
|
||||||
|
handleP80ListenerStateChange(enabled);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
initPort80ListenerSetting();
|
||||||
|
|
||||||
function initHTTPtoHTTPSRedirectSetting(){
|
function initHTTPtoHTTPSRedirectSetting(){
|
||||||
$.get("/api/proxy/useHttpsRedirect", function(data){
|
$.get("/api/proxy/useHttpsRedirect", function(data){
|
||||||
if (data == true){
|
if (data == true){
|
||||||
@ -356,8 +402,6 @@
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
initHTTPtoHTTPSRedirectSetting();
|
initHTTPtoHTTPSRedirectSetting();
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Matching Domain</th>
|
<th>Matching Domain</th>
|
||||||
<th>Proxy To</th>
|
<th>Proxy To</th>
|
||||||
<th>TLS/SSL Verification</th>
|
|
||||||
<th>Basic Auth</th>
|
<th>Basic Auth</th>
|
||||||
<th class="no-sort" style="min-width: 7.2em;">Actions</th>
|
<th class="no-sort" style="min-width: 7.2em;">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -41,19 +40,14 @@
|
|||||||
let subdData = encodeURIComponent(JSON.stringify(subd));
|
let subdData = encodeURIComponent(JSON.stringify(subd));
|
||||||
if (subd.RequireTLS){
|
if (subd.RequireTLS){
|
||||||
tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
|
tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
|
||||||
|
if (subd.SkipCertValidations){
|
||||||
|
tlsIcon = `<i class="yellow lock icon" title="TLS/SSL mode without verification"></i>`
|
||||||
}
|
}
|
||||||
|
|
||||||
let tlsVerificationField = "";
|
|
||||||
if (subd.RequireTLS){
|
|
||||||
tlsVerificationField = !subd.SkipCertValidations?`<i class="ui green check icon"></i>`:`<i class="ui yellow exclamation circle icon" title="TLS/SSL Verification will be skipped on this host"></i>`
|
|
||||||
}else{
|
|
||||||
tlsVerificationField = "N/A"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#subdList").append(`<tr eptuuid="${subd.RootOrMatchingDomain}" payload="${subdData}" class="subdEntry">
|
$("#subdList").append(`<tr eptuuid="${subd.RootOrMatchingDomain}" payload="${subdData}" class="subdEntry">
|
||||||
<td data-label="" editable="false"><a href="//${subd.RootOrMatchingDomain}" target="_blank">${subd.RootOrMatchingDomain}</a></td>
|
<td data-label="" editable="true" datatype="inbound"><a href="//${subd.RootOrMatchingDomain}" target="_blank">${subd.RootOrMatchingDomain}</a></td>
|
||||||
<td data-label="" editable="true" datatype="domain">${subd.Domain} ${tlsIcon}</td>
|
<td data-label="" editable="true" datatype="domain">${subd.Domain} ${tlsIcon}</td>
|
||||||
<td data-label="" editable="true" datatype="skipver">${tlsVerificationField}</td>
|
|
||||||
<td data-label="" editable="true" datatype="basicauth">${subd.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td>
|
<td data-label="" editable="true" datatype="basicauth">${subd.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td>
|
||||||
<td class="center aligned" editable="true" datatype="action" data-label="">
|
<td class="center aligned" editable="true" datatype="action" data-label="">
|
||||||
<button class="ui circular mini basic icon button editBtn" onclick='editEndpoint("subd","${subd.RootOrMatchingDomain}")'><i class="edit icon"></i></button>
|
<button class="ui circular mini basic icon button editBtn" onclick='editEndpoint("subd","${subd.RootOrMatchingDomain}")'><i class="edit icon"></i></button>
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
|
|
||||||
let id = value[0].ID;
|
let id = value[0].ID;
|
||||||
let name = value[0].Name;
|
let name = value[0].Name;
|
||||||
let url = value[0].URL;
|
let url = value[value.length - 1].URL;
|
||||||
let protocol = value[0].Protocol;
|
let protocol = value[0].Protocol;
|
||||||
|
|
||||||
//Generate the status dot
|
//Generate the status dot
|
||||||
@ -112,6 +112,9 @@
|
|||||||
if (thisStatus.StatusCode >= 500 && thisStatus.StatusCode < 600){
|
if (thisStatus.StatusCode >= 500 && thisStatus.StatusCode < 600){
|
||||||
//Special type of error, cause by downstream reverse proxy
|
//Special type of error, cause by downstream reverse proxy
|
||||||
dotType = "error";
|
dotType = "error";
|
||||||
|
}else if (thisStatus.StatusCode == 401){
|
||||||
|
//Unauthorized error
|
||||||
|
dotType = "error";
|
||||||
}else{
|
}else{
|
||||||
dotType = "offline";
|
dotType = "offline";
|
||||||
}
|
}
|
||||||
@ -141,6 +144,28 @@
|
|||||||
currentOnlineStatus = `<i class="exclamation circle icon"></i> Misconfigured`;
|
currentOnlineStatus = `<i class="exclamation circle icon"></i> Misconfigured`;
|
||||||
onlineStatusCss = `color: #f38020;`;
|
onlineStatusCss = `color: #f38020;`;
|
||||||
reminderEle = `<small style="${onlineStatusCss}">Downstream proxy server is online with misconfigured settings</small>`;
|
reminderEle = `<small style="${onlineStatusCss}">Downstream proxy server is online with misconfigured settings</small>`;
|
||||||
|
}else if (value[value.length - 1].StatusCode >= 400 && value[value.length - 1].StatusCode <= 405){
|
||||||
|
switch(value[value.length - 1].StatusCode){
|
||||||
|
case 400:
|
||||||
|
currentOnlineStatus = `<i class="exclamation circle icon"></i> Bad Request`;
|
||||||
|
break;
|
||||||
|
case 401:
|
||||||
|
currentOnlineStatus = `<i class="exclamation circle icon"></i> Unauthorized`;
|
||||||
|
break;
|
||||||
|
case 403:
|
||||||
|
currentOnlineStatus = `<i class="exclamation circle icon"></i> Forbidden`;
|
||||||
|
break;
|
||||||
|
case 404:
|
||||||
|
currentOnlineStatus = `<i class="exclamation circle icon"></i> Not Found`;
|
||||||
|
break;
|
||||||
|
case 405:
|
||||||
|
currentOnlineStatus = `<i class="exclamation circle icon"></i> Method Not Allowed`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
onlineStatusCss = `color: #f38020;`;
|
||||||
|
reminderEle = `<small style="${onlineStatusCss}">Target online but not accessible</small>`;
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
currentOnlineStatus = `<i class="circle icon"></i> Offline`;
|
currentOnlineStatus = `<i class="circle icon"></i> Offline`;
|
||||||
onlineStatusCss = `color: #df484a;`;
|
onlineStatusCss = `color: #df484a;`;
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Virtual Directory</th>
|
<th>Virtual Directory</th>
|
||||||
<th>Proxy To</th>
|
<th>Proxy To</th>
|
||||||
<th>TLS/SSL Verification</th>
|
|
||||||
<th>Basic Auth</th>
|
<th>Basic Auth</th>
|
||||||
<th class="no-sort" style="min-width: 7.2em;">Actions</th>
|
<th class="no-sort" style="min-width: 7.2em;">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -43,6 +42,9 @@
|
|||||||
let vdirData = encodeURIComponent(JSON.stringify(vdir));
|
let vdirData = encodeURIComponent(JSON.stringify(vdir));
|
||||||
if (vdir.RequireTLS){
|
if (vdir.RequireTLS){
|
||||||
tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
|
tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
|
||||||
|
if (vdir.SkipCertValidations){
|
||||||
|
tlsIcon = `<i class="yellow lock icon" title="TLS/SSL mode without verification"></i>`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tlsVerificationField = "";
|
let tlsVerificationField = "";
|
||||||
@ -55,7 +57,6 @@
|
|||||||
$("#vdirList").append(`<tr eptuuid="${vdir.RootOrMatchingDomain}" payload="${vdirData}" class="vdirEntry">
|
$("#vdirList").append(`<tr eptuuid="${vdir.RootOrMatchingDomain}" payload="${vdirData}" class="vdirEntry">
|
||||||
<td data-label="" editable="false">${vdir.RootOrMatchingDomain}</td>
|
<td data-label="" editable="false">${vdir.RootOrMatchingDomain}</td>
|
||||||
<td data-label="" editable="true" datatype="domain">${vdir.Domain} ${tlsIcon}</td>
|
<td data-label="" editable="true" datatype="domain">${vdir.Domain} ${tlsIcon}</td>
|
||||||
<td data-label="" editable="true" datatype="skipver">${tlsVerificationField}</td>
|
|
||||||
<td data-label="" editable="true" datatype="basicauth">${vdir.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td>
|
<td data-label="" editable="true" datatype="basicauth">${vdir.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td>
|
||||||
<td class="center aligned" editable="true" datatype="action" data-label="">
|
<td class="center aligned" editable="true" datatype="action" data-label="">
|
||||||
<button class="ui circular mini basic icon button editBtn" onclick='editEndpoint("vdir","${vdir.RootOrMatchingDomain}")'><i class="edit icon"></i></button>
|
<button class="ui circular mini basic icon button editBtn" onclick='editEndpoint("vdir","${vdir.RootOrMatchingDomain}")'><i class="edit icon"></i></button>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<h3>Web Server Settings</h3>
|
<h3>Web Server Settings</h3>
|
||||||
<div class="ui form">
|
<div class="ui form">
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
<div class="ui toggle checkbox">
|
<div class="ui toggle checkbox webservRootDisabled">
|
||||||
<input id="webserv_enable" type="checkbox" class="hidden">
|
<input id="webserv_enable" type="checkbox" class="hidden">
|
||||||
<label>Enable Static Web Server</label>
|
<label>Enable Static Web Server</label>
|
||||||
</div>
|
</div>
|
||||||
@ -37,7 +37,7 @@
|
|||||||
See the -webserv flag for more details.
|
See the -webserv flag for more details.
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field webservRootDisabled">
|
||||||
<label>Port Number</label>
|
<label>Port Number</label>
|
||||||
<input id="webserv_listenPort" type="number" step="1" min="0" max="65535" value="8081" onchange="updateWebServLinkExample(this.value);">
|
<input id="webserv_listenPort" type="number" step="1" min="0" max="65535" value="8081" onchange="updateWebServLinkExample(this.value);">
|
||||||
<small>Use <code>http://127.0.0.1:<span class="webserv_port">8081</span></code> in proxy rules to access the web server</small>
|
<small>Use <code>http://127.0.0.1:<span class="webserv_port">8081</span></code> in proxy rules to access the web server</small>
|
||||||
|
@ -19,7 +19,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -104,6 +103,20 @@ func HandleCountryDistrSummary(w http.ResponseWriter, r *http.Request) {
|
|||||||
/*
|
/*
|
||||||
Up Time Monitor
|
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)
|
||||||
|
go func() {
|
||||||
|
uptimeMonitor.ExecuteUptimeCheck()
|
||||||
|
}()
|
||||||
|
|
||||||
|
SystemWideLogger.PrintAndLog("Uptime", "Uptime monitor config updated", nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Generate uptime monitor targets from reverse proxy rules
|
// Generate uptime monitor targets from reverse proxy rules
|
||||||
func GetUptimeTargetsFromReverseProxyRules(dp *dynamicproxy.Router) []*uptime.Target {
|
func GetUptimeTargetsFromReverseProxyRules(dp *dynamicproxy.Router) []*uptime.Target {
|
||||||
subds := dp.GetSDProxyEndpointsAsMap()
|
subds := dp.GetSDProxyEndpointsAsMap()
|
||||||
@ -263,7 +276,7 @@ func HandleWakeOnLan(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
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)
|
err := wakeonlan.WakeTarget(wake)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.SendErrorResponse(w, err.Error())
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user