mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-01 13:17:21 +02:00
commit
0a734e0bd3
@ -30,6 +30,7 @@ VOLUME [ "/opt/zoraxy/config/" ]
|
||||
WORKDIR /opt/zoraxy/config/
|
||||
|
||||
ENV AUTORENEW="86400"
|
||||
ENV EARLYRENEW="30"
|
||||
ENV FASTGEOIP="false"
|
||||
ENV MDNS="true"
|
||||
ENV MDNSNAME="''"
|
||||
@ -42,6 +43,6 @@ ENV WEBROOT="./www"
|
||||
ENV ZTAUTH="''"
|
||||
ENV ZTPORT="9993"
|
||||
|
||||
ENTRYPOINT "zoraxy" "-docker=true" "-autorenew=${AUTORENEW}" "-fastgeoip=${FASTGEOIP}" "-mdns=${MDNS}" "-mdnsname=${MDNSNAME}" "-noauth=${NOAUTH}" "-port=:${PORT}" "-sshlb=${SSHLB}" "-version=${VERSION}" "-webfm=${WEBFM}" "-webroot=${WEBROOT}" "-ztauth=${ZTAUTH}" "-ztport=${ZTPORT}"
|
||||
ENTRYPOINT "zoraxy" "-docker=true" "-autorenew=${AUTORENEW}" "-earlyrenew=${EARLYRENEW}" "-fastgeoip=${FASTGEOIP}" "-mdns=${MDNS}" "-mdnsname=${MDNSNAME}" "-noauth=${NOAUTH}" "-port=:${PORT}" "-sshlb=${SSHLB}" "-version=${VERSION}" "-webfm=${WEBFM}" "-webroot=${WEBROOT}" "-ztauth=${ZTAUTH}" "-ztport=${ZTPORT}"
|
||||
|
||||
HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=3 CMD nc -vz 127.0.0.1 $PORT || exit 1
|
||||
|
@ -19,7 +19,7 @@ clean:
|
||||
|
||||
$(PLATFORMS):
|
||||
@echo "Building $(os)/$(arch)"
|
||||
GOROOT_FINAL=Git/ GOOS=$(os) GOARCH=$(arch) $(if $(filter linux/arm,$(os)/$(arch)),GOARM=6,) go build -o './dist/zoraxy_$(os)_$(arch)' -ldflags "-s -w" -trimpath
|
||||
GOROOT_FINAL=Git/ GOOS=$(os) GOARCH=$(arch) $(if $(filter linux/arm,$(os)/$(arch)),GOARM=6,) CGO_ENABLED="0" go build -o './dist/zoraxy_$(os)_$(arch)' -ldflags "-s -w" -trimpath
|
||||
# GOROOT_FINAL=Git/ GOOS=$(os) GOARCH=$(arch) GOARM=6 go build -o './dist/zoraxy_$(os)_$(arch)' -ldflags "-s -w" -trimpath
|
||||
|
||||
|
||||
|
34
src/api.go
34
src/api.go
@ -22,11 +22,11 @@ import (
|
||||
|
||||
var requireAuth = true
|
||||
|
||||
func initAPIs() {
|
||||
|
||||
func initAPIs(targetMux *http.ServeMux) {
|
||||
authRouter := auth.NewManagedHTTPRouter(auth.RouterOption{
|
||||
AuthAgent: authAgent,
|
||||
RequireAuth: requireAuth,
|
||||
TargetMux: targetMux,
|
||||
DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "401 - Unauthorized", http.StatusUnauthorized)
|
||||
},
|
||||
@ -37,12 +37,12 @@ func initAPIs() {
|
||||
if development {
|
||||
fs = http.FileServer(http.Dir("web/"))
|
||||
}
|
||||
//Add a layer of middleware for advance control
|
||||
//Add a layer of middleware for advance control
|
||||
advHandler := FSHandler(fs)
|
||||
http.Handle("/", advHandler)
|
||||
targetMux.Handle("/", advHandler)
|
||||
|
||||
//Authentication APIs
|
||||
registerAuthAPIs(requireAuth)
|
||||
registerAuthAPIs(requireAuth, targetMux)
|
||||
|
||||
//Reverse proxy
|
||||
authRouter.HandleFunc("/api/proxy/enable", ReverseProxyHandleOnOff)
|
||||
@ -77,6 +77,8 @@ func initAPIs() {
|
||||
authRouter.HandleFunc("/api/proxy/header/add", HandleCustomHeaderAdd)
|
||||
authRouter.HandleFunc("/api/proxy/header/remove", HandleCustomHeaderRemove)
|
||||
authRouter.HandleFunc("/api/proxy/header/handleHSTS", HandleHSTSState)
|
||||
authRouter.HandleFunc("/api/proxy/header/handleHopByHop", HandleHopByHop)
|
||||
authRouter.HandleFunc("/api/proxy/header/handleHostOverwrite", HandleHostOverwrite)
|
||||
authRouter.HandleFunc("/api/proxy/header/handlePermissionPolicy", HandlePermissionPolicy)
|
||||
//Reverse proxy auth related APIs
|
||||
authRouter.HandleFunc("/api/proxy/auth/exceptions/list", ListProxyBasicAuthExceptionPaths)
|
||||
@ -185,8 +187,8 @@ func initAPIs() {
|
||||
authRouter.HandleFunc("/api/tools/fwdproxy/port", forwardProxy.HandlePort)
|
||||
|
||||
//Account Reset
|
||||
http.HandleFunc("/api/account/reset", HandleAdminAccountResetEmail)
|
||||
http.HandleFunc("/api/account/new", HandleNewPasswordSetup)
|
||||
targetMux.HandleFunc("/api/account/reset", HandleAdminAccountResetEmail)
|
||||
targetMux.HandleFunc("/api/account/new", HandleNewPasswordSetup)
|
||||
|
||||
//ACME & Auto Renewer
|
||||
authRouter.HandleFunc("/api/acme/listExpiredDomains", acmeHandler.HandleGetExpiredDomains)
|
||||
@ -226,7 +228,7 @@ func initAPIs() {
|
||||
authRouter.HandleFunc("/api/docker/containers", DockerUXOptimizer.HandleDockerContainersList)
|
||||
|
||||
//Others
|
||||
http.HandleFunc("/api/info/x", HandleZoraxyInfo)
|
||||
targetMux.HandleFunc("/api/info/x", HandleZoraxyInfo)
|
||||
authRouter.HandleFunc("/api/info/geoip", HandleGeoIpLookup)
|
||||
authRouter.HandleFunc("/api/conf/export", ExportConfigAsZip)
|
||||
authRouter.HandleFunc("/api/conf/import", ImportConfigFromZip)
|
||||
@ -241,18 +243,18 @@ func initAPIs() {
|
||||
}
|
||||
|
||||
// Function to renders Auth related APIs
|
||||
func registerAuthAPIs(requireAuth bool) {
|
||||
func registerAuthAPIs(requireAuth bool, targetMux *http.ServeMux) {
|
||||
//Auth APIs
|
||||
http.HandleFunc("/api/auth/login", authAgent.HandleLogin)
|
||||
http.HandleFunc("/api/auth/logout", authAgent.HandleLogout)
|
||||
http.HandleFunc("/api/auth/checkLogin", func(w http.ResponseWriter, r *http.Request) {
|
||||
targetMux.HandleFunc("/api/auth/login", authAgent.HandleLogin)
|
||||
targetMux.HandleFunc("/api/auth/logout", authAgent.HandleLogout)
|
||||
targetMux.HandleFunc("/api/auth/checkLogin", func(w http.ResponseWriter, r *http.Request) {
|
||||
if requireAuth {
|
||||
authAgent.CheckLogin(w, r)
|
||||
} else {
|
||||
utils.SendJSONResponse(w, "true")
|
||||
}
|
||||
})
|
||||
http.HandleFunc("/api/auth/username", func(w http.ResponseWriter, r *http.Request) {
|
||||
targetMux.HandleFunc("/api/auth/username", func(w http.ResponseWriter, r *http.Request) {
|
||||
username, err := authAgent.GetUserName(w, r)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||
@ -262,12 +264,12 @@ func registerAuthAPIs(requireAuth bool) {
|
||||
js, _ := json.Marshal(username)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
})
|
||||
http.HandleFunc("/api/auth/userCount", func(w http.ResponseWriter, r *http.Request) {
|
||||
targetMux.HandleFunc("/api/auth/userCount", func(w http.ResponseWriter, r *http.Request) {
|
||||
uc := authAgent.GetUserCounts()
|
||||
js, _ := json.Marshal(uc)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
})
|
||||
http.HandleFunc("/api/auth/register", func(w http.ResponseWriter, r *http.Request) {
|
||||
targetMux.HandleFunc("/api/auth/register", func(w http.ResponseWriter, r *http.Request) {
|
||||
if authAgent.GetUserCounts() == 0 {
|
||||
//Allow register root admin
|
||||
authAgent.HandleRegisterWithoutEmail(w, r, func(username, reserved string) {
|
||||
@ -278,7 +280,7 @@ func registerAuthAPIs(requireAuth bool) {
|
||||
utils.SendErrorResponse(w, "Root management account already exists")
|
||||
}
|
||||
})
|
||||
http.HandleFunc("/api/auth/changePassword", func(w http.ResponseWriter, r *http.Request) {
|
||||
targetMux.HandleFunc("/api/auth/changePassword", func(w http.ResponseWriter, r *http.Request) {
|
||||
username, err := authAgent.GetUserName(w, r)
|
||||
if err != nil {
|
||||
http.Error(w, "401 - Unauthorized", http.StatusUnauthorized)
|
||||
|
23
src/cert.go
23
src/cert.go
@ -182,27 +182,28 @@ func handleToggleTLSProxy(w http.ResponseWriter, r *http.Request) {
|
||||
sysdb.Read("settings", "usetls", ¤tTlsSetting)
|
||||
}
|
||||
|
||||
newState, err := utils.PostPara(r, "set")
|
||||
if err != nil {
|
||||
//No setting. Get the current status
|
||||
if r.Method == http.MethodGet {
|
||||
//Get the current status
|
||||
js, _ := json.Marshal(currentTlsSetting)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
} else {
|
||||
if newState == "true" {
|
||||
} else if r.Method == http.MethodPost {
|
||||
newState, err := utils.PostBool(r, "set")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "new state not set or invalid")
|
||||
return
|
||||
}
|
||||
if newState {
|
||||
sysdb.Write("settings", "usetls", true)
|
||||
SystemWideLogger.Println("Enabling TLS mode on reverse proxy")
|
||||
dynamicProxyRouter.UpdateTLSSetting(true)
|
||||
} else if newState == "false" {
|
||||
} else {
|
||||
sysdb.Write("settings", "usetls", false)
|
||||
SystemWideLogger.Println("Disabling TLS mode on reverse proxy")
|
||||
dynamicProxyRouter.UpdateTLSSetting(false)
|
||||
} else {
|
||||
utils.SendErrorResponse(w, "invalid state given. Only support true or false")
|
||||
return
|
||||
}
|
||||
|
||||
utils.SendOK(w)
|
||||
|
||||
} else {
|
||||
http.Error(w, "405 - Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,6 +95,7 @@ require (
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.2 // indirect
|
||||
github.com/gophercloud/gophercloud v1.0.0 // indirect
|
||||
github.com/gorilla/csrf v1.7.2 // indirect
|
||||
github.com/gorilla/css v1.0.1 // indirect
|
||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
|
@ -317,6 +317,8 @@ github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7
|
||||
github.com/gophercloud/gophercloud v1.0.0 h1:9nTGx0jizmHxDobe4mck89FyQHVyA3CaXLIUSGJjP9k=
|
||||
github.com/gophercloud/gophercloud v1.0.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/csrf v1.7.2 h1:oTUjx0vyf2T+wkrx09Trsev1TE+/EbDAeHtSTbtC2eI=
|
||||
github.com/gorilla/csrf v1.7.2/go.mod h1:F1Fj3KG23WYHE6gozCmBAezKookxbIvUJT+121wTuLk=
|
||||
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
|
28
src/main.go
28
src/main.go
@ -12,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/gorilla/csrf"
|
||||
"imuslab.com/zoraxy/mod/access"
|
||||
"imuslab.com/zoraxy/mod/acme"
|
||||
"imuslab.com/zoraxy/mod/auth"
|
||||
@ -50,6 +51,7 @@ var ztAuthToken = flag.String("ztauth", "", "ZeroTier authtoken for the local no
|
||||
var ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port")
|
||||
var runningInDocker = flag.Bool("docker", false, "Run Zoraxy in docker compatibility mode")
|
||||
var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)")
|
||||
var acmeCertAutoRenewDays = flag.Int("earlyrenew", 30, "Number of days to early renew a soon expiring certificate (days)")
|
||||
var enableHighSpeedGeoIPLookup = flag.Bool("fastgeoip", false, "Enable high speed geoip lookup, require 1GB extra memory (Not recommend for low end devices)")
|
||||
var staticWebServerRoot = flag.String("webroot", "./www", "Static web server root folder. Only allow chnage in start paramters")
|
||||
var allowWebFileManager = flag.Bool("webfm", true, "Enable web file manager for static web server root folder")
|
||||
@ -57,7 +59,7 @@ var enableAutoUpdate = flag.Bool("cfgupgrade", true, "Enable auto config upgrade
|
||||
|
||||
var (
|
||||
name = "Zoraxy"
|
||||
version = "3.0.9"
|
||||
version = "3.1.0"
|
||||
nodeUUID = "generic" //System uuid, in uuidv4 format
|
||||
development = false //Set this to false to use embedded web fs
|
||||
bootTime = time.Now().Unix()
|
||||
@ -71,10 +73,12 @@ var (
|
||||
/*
|
||||
Handler Modules
|
||||
*/
|
||||
sysdb *database.Database //System database
|
||||
authAgent *auth.AuthAgent //Authentication agent
|
||||
tlsCertManager *tlscert.Manager //TLS / SSL management
|
||||
redirectTable *redirection.RuleTable //Handle special redirection rule sets
|
||||
sysdb *database.Database //System database
|
||||
authAgent *auth.AuthAgent //Authentication agent
|
||||
tlsCertManager *tlscert.Manager //TLS / SSL management
|
||||
redirectTable *redirection.RuleTable //Handle special redirection rule sets
|
||||
webminPanelMux *http.ServeMux //Server mux for handling webmin panel APIs
|
||||
csrfMiddleware func(http.Handler) http.Handler //CSRF protection middleware
|
||||
|
||||
pathRuleHandler *pathrule.Handler //Handle specific path blocking or custom headers
|
||||
geodbStore *geodb.Store //GeoIP database, for resolving IP into country code
|
||||
@ -175,12 +179,22 @@ func main() {
|
||||
}
|
||||
nodeUUID = string(uuidBytes)
|
||||
|
||||
//Create a new webmin mux and csrf middleware layer
|
||||
webminPanelMux = http.NewServeMux()
|
||||
csrfMiddleware = csrf.Protect(
|
||||
[]byte(nodeUUID),
|
||||
csrf.CookieName("zoraxy-csrf"),
|
||||
csrf.Secure(false),
|
||||
csrf.Path("/"),
|
||||
csrf.SameSite(csrf.SameSiteLaxMode),
|
||||
)
|
||||
|
||||
//Startup all modules
|
||||
startupSequence()
|
||||
|
||||
//Initiate management interface APIs
|
||||
requireAuth = !(*noauth)
|
||||
initAPIs()
|
||||
initAPIs(webminPanelMux)
|
||||
|
||||
//Start the reverse proxy server in go routine
|
||||
go func() {
|
||||
@ -193,7 +207,7 @@ func main() {
|
||||
finalSequence()
|
||||
|
||||
SystemWideLogger.Println("Zoraxy started. Visit control panel at http://localhost" + *webUIPort)
|
||||
err = http.ListenAndServe(*webUIPort, nil)
|
||||
err = http.ListenAndServe(*webUIPort, csrfMiddleware(webminPanelMux))
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -143,6 +143,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return alidns.NewDNSProviderConfig(cfg)
|
||||
case "allinkl":
|
||||
cfg := allinkl.NewDefaultConfig()
|
||||
@ -150,6 +151,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return allinkl.NewDNSProviderConfig(cfg)
|
||||
case "arvancloud":
|
||||
cfg := arvancloud.NewDefaultConfig()
|
||||
@ -157,6 +159,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return arvancloud.NewDNSProviderConfig(cfg)
|
||||
case "auroradns":
|
||||
cfg := auroradns.NewDefaultConfig()
|
||||
@ -164,6 +167,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return auroradns.NewDNSProviderConfig(cfg)
|
||||
case "autodns":
|
||||
cfg := autodns.NewDefaultConfig()
|
||||
@ -171,6 +175,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return autodns.NewDNSProviderConfig(cfg)
|
||||
case "azure":
|
||||
cfg := azure.NewDefaultConfig()
|
||||
@ -178,6 +183,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return azure.NewDNSProviderConfig(cfg)
|
||||
case "azuredns":
|
||||
cfg := azuredns.NewDefaultConfig()
|
||||
@ -185,6 +191,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return azuredns.NewDNSProviderConfig(cfg)
|
||||
case "bindman":
|
||||
cfg := bindman.NewDefaultConfig()
|
||||
@ -192,6 +199,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return bindman.NewDNSProviderConfig(cfg)
|
||||
case "bluecat":
|
||||
cfg := bluecat.NewDefaultConfig()
|
||||
@ -199,6 +207,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return bluecat.NewDNSProviderConfig(cfg)
|
||||
case "brandit":
|
||||
cfg := brandit.NewDefaultConfig()
|
||||
@ -206,6 +215,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return brandit.NewDNSProviderConfig(cfg)
|
||||
case "bunny":
|
||||
cfg := bunny.NewDefaultConfig()
|
||||
@ -213,6 +223,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return bunny.NewDNSProviderConfig(cfg)
|
||||
case "checkdomain":
|
||||
cfg := checkdomain.NewDefaultConfig()
|
||||
@ -220,6 +231,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return checkdomain.NewDNSProviderConfig(cfg)
|
||||
case "civo":
|
||||
cfg := civo.NewDefaultConfig()
|
||||
@ -227,6 +239,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return civo.NewDNSProviderConfig(cfg)
|
||||
case "clouddns":
|
||||
cfg := clouddns.NewDefaultConfig()
|
||||
@ -234,6 +247,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return clouddns.NewDNSProviderConfig(cfg)
|
||||
case "cloudflare":
|
||||
cfg := cloudflare.NewDefaultConfig()
|
||||
@ -241,6 +255,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return cloudflare.NewDNSProviderConfig(cfg)
|
||||
case "cloudns":
|
||||
cfg := cloudns.NewDefaultConfig()
|
||||
@ -248,6 +263,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return cloudns.NewDNSProviderConfig(cfg)
|
||||
case "cloudru":
|
||||
cfg := cloudru.NewDefaultConfig()
|
||||
@ -255,6 +271,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return cloudru.NewDNSProviderConfig(cfg)
|
||||
case "cloudxns":
|
||||
cfg := cloudxns.NewDefaultConfig()
|
||||
@ -262,6 +279,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return cloudxns.NewDNSProviderConfig(cfg)
|
||||
case "conoha":
|
||||
cfg := conoha.NewDefaultConfig()
|
||||
@ -269,6 +287,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return conoha.NewDNSProviderConfig(cfg)
|
||||
case "constellix":
|
||||
cfg := constellix.NewDefaultConfig()
|
||||
@ -276,6 +295,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return constellix.NewDNSProviderConfig(cfg)
|
||||
case "cpanel":
|
||||
cfg := cpanel.NewDefaultConfig()
|
||||
@ -283,6 +303,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return cpanel.NewDNSProviderConfig(cfg)
|
||||
case "derak":
|
||||
cfg := derak.NewDefaultConfig()
|
||||
@ -290,6 +311,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return derak.NewDNSProviderConfig(cfg)
|
||||
case "desec":
|
||||
cfg := desec.NewDefaultConfig()
|
||||
@ -297,6 +319,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return desec.NewDNSProviderConfig(cfg)
|
||||
case "digitalocean":
|
||||
cfg := digitalocean.NewDefaultConfig()
|
||||
@ -304,6 +327,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return digitalocean.NewDNSProviderConfig(cfg)
|
||||
case "dnshomede":
|
||||
cfg := dnshomede.NewDefaultConfig()
|
||||
@ -311,6 +335,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return dnshomede.NewDNSProviderConfig(cfg)
|
||||
case "dnsimple":
|
||||
cfg := dnsimple.NewDefaultConfig()
|
||||
@ -318,6 +343,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return dnsimple.NewDNSProviderConfig(cfg)
|
||||
case "dnsmadeeasy":
|
||||
cfg := dnsmadeeasy.NewDefaultConfig()
|
||||
@ -325,6 +351,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return dnsmadeeasy.NewDNSProviderConfig(cfg)
|
||||
case "dnspod":
|
||||
cfg := dnspod.NewDefaultConfig()
|
||||
@ -332,6 +359,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return dnspod.NewDNSProviderConfig(cfg)
|
||||
case "dode":
|
||||
cfg := dode.NewDefaultConfig()
|
||||
@ -339,6 +367,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return dode.NewDNSProviderConfig(cfg)
|
||||
case "domeneshop":
|
||||
cfg := domeneshop.NewDefaultConfig()
|
||||
@ -346,6 +375,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return domeneshop.NewDNSProviderConfig(cfg)
|
||||
case "dreamhost":
|
||||
cfg := dreamhost.NewDefaultConfig()
|
||||
@ -353,6 +383,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return dreamhost.NewDNSProviderConfig(cfg)
|
||||
case "duckdns":
|
||||
cfg := duckdns.NewDefaultConfig()
|
||||
@ -360,6 +391,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return duckdns.NewDNSProviderConfig(cfg)
|
||||
case "dyn":
|
||||
cfg := dyn.NewDefaultConfig()
|
||||
@ -367,6 +399,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return dyn.NewDNSProviderConfig(cfg)
|
||||
case "dynu":
|
||||
cfg := dynu.NewDefaultConfig()
|
||||
@ -374,6 +407,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return dynu.NewDNSProviderConfig(cfg)
|
||||
case "easydns":
|
||||
cfg := easydns.NewDefaultConfig()
|
||||
@ -381,6 +415,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return easydns.NewDNSProviderConfig(cfg)
|
||||
case "efficientip":
|
||||
cfg := efficientip.NewDefaultConfig()
|
||||
@ -388,6 +423,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return efficientip.NewDNSProviderConfig(cfg)
|
||||
case "epik":
|
||||
cfg := epik.NewDefaultConfig()
|
||||
@ -395,6 +431,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return epik.NewDNSProviderConfig(cfg)
|
||||
case "exoscale":
|
||||
cfg := exoscale.NewDefaultConfig()
|
||||
@ -402,6 +439,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return exoscale.NewDNSProviderConfig(cfg)
|
||||
case "freemyip":
|
||||
cfg := freemyip.NewDefaultConfig()
|
||||
@ -409,6 +447,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return freemyip.NewDNSProviderConfig(cfg)
|
||||
case "gandi":
|
||||
cfg := gandi.NewDefaultConfig()
|
||||
@ -416,6 +455,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return gandi.NewDNSProviderConfig(cfg)
|
||||
case "gandiv5":
|
||||
cfg := gandiv5.NewDefaultConfig()
|
||||
@ -423,6 +463,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return gandiv5.NewDNSProviderConfig(cfg)
|
||||
case "gcore":
|
||||
cfg := gcore.NewDefaultConfig()
|
||||
@ -430,6 +471,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return gcore.NewDNSProviderConfig(cfg)
|
||||
case "glesys":
|
||||
cfg := glesys.NewDefaultConfig()
|
||||
@ -437,6 +479,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return glesys.NewDNSProviderConfig(cfg)
|
||||
case "godaddy":
|
||||
cfg := godaddy.NewDefaultConfig()
|
||||
@ -444,6 +487,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return godaddy.NewDNSProviderConfig(cfg)
|
||||
case "googledomains":
|
||||
cfg := googledomains.NewDefaultConfig()
|
||||
@ -451,6 +495,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return googledomains.NewDNSProviderConfig(cfg)
|
||||
case "hetzner":
|
||||
cfg := hetzner.NewDefaultConfig()
|
||||
@ -458,6 +503,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return hetzner.NewDNSProviderConfig(cfg)
|
||||
case "hostingde":
|
||||
cfg := hostingde.NewDefaultConfig()
|
||||
@ -465,6 +511,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return hostingde.NewDNSProviderConfig(cfg)
|
||||
case "hosttech":
|
||||
cfg := hosttech.NewDefaultConfig()
|
||||
@ -472,6 +519,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return hosttech.NewDNSProviderConfig(cfg)
|
||||
case "httpnet":
|
||||
cfg := httpnet.NewDefaultConfig()
|
||||
@ -479,6 +527,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return httpnet.NewDNSProviderConfig(cfg)
|
||||
case "hyperone":
|
||||
cfg := hyperone.NewDefaultConfig()
|
||||
@ -486,6 +535,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return hyperone.NewDNSProviderConfig(cfg)
|
||||
case "ibmcloud":
|
||||
cfg := ibmcloud.NewDefaultConfig()
|
||||
@ -493,6 +543,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return ibmcloud.NewDNSProviderConfig(cfg)
|
||||
case "iij":
|
||||
cfg := iij.NewDefaultConfig()
|
||||
@ -500,6 +551,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return iij.NewDNSProviderConfig(cfg)
|
||||
case "iijdpf":
|
||||
cfg := iijdpf.NewDefaultConfig()
|
||||
@ -507,6 +559,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return iijdpf.NewDNSProviderConfig(cfg)
|
||||
case "infoblox":
|
||||
cfg := infoblox.NewDefaultConfig()
|
||||
@ -514,6 +567,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return infoblox.NewDNSProviderConfig(cfg)
|
||||
case "infomaniak":
|
||||
cfg := infomaniak.NewDefaultConfig()
|
||||
@ -521,6 +575,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return infomaniak.NewDNSProviderConfig(cfg)
|
||||
case "internetbs":
|
||||
cfg := internetbs.NewDefaultConfig()
|
||||
@ -528,6 +583,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return internetbs.NewDNSProviderConfig(cfg)
|
||||
case "inwx":
|
||||
cfg := inwx.NewDefaultConfig()
|
||||
@ -535,6 +591,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return inwx.NewDNSProviderConfig(cfg)
|
||||
case "ionos":
|
||||
cfg := ionos.NewDefaultConfig()
|
||||
@ -542,6 +599,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return ionos.NewDNSProviderConfig(cfg)
|
||||
case "ipv64":
|
||||
cfg := ipv64.NewDefaultConfig()
|
||||
@ -549,6 +607,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return ipv64.NewDNSProviderConfig(cfg)
|
||||
case "iwantmyname":
|
||||
cfg := iwantmyname.NewDefaultConfig()
|
||||
@ -556,6 +615,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return iwantmyname.NewDNSProviderConfig(cfg)
|
||||
case "joker":
|
||||
cfg := joker.NewDefaultConfig()
|
||||
@ -563,6 +623,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return joker.NewDNSProviderConfig(cfg)
|
||||
case "liara":
|
||||
cfg := liara.NewDefaultConfig()
|
||||
@ -570,6 +631,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return liara.NewDNSProviderConfig(cfg)
|
||||
case "lightsail":
|
||||
cfg := lightsail.NewDefaultConfig()
|
||||
@ -577,6 +639,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return lightsail.NewDNSProviderConfig(cfg)
|
||||
case "linode":
|
||||
cfg := linode.NewDefaultConfig()
|
||||
@ -584,6 +647,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return linode.NewDNSProviderConfig(cfg)
|
||||
case "liquidweb":
|
||||
cfg := liquidweb.NewDefaultConfig()
|
||||
@ -591,6 +655,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return liquidweb.NewDNSProviderConfig(cfg)
|
||||
case "loopia":
|
||||
cfg := loopia.NewDefaultConfig()
|
||||
@ -598,6 +663,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return loopia.NewDNSProviderConfig(cfg)
|
||||
case "luadns":
|
||||
cfg := luadns.NewDefaultConfig()
|
||||
@ -605,6 +671,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return luadns.NewDNSProviderConfig(cfg)
|
||||
case "mailinabox":
|
||||
cfg := mailinabox.NewDefaultConfig()
|
||||
@ -612,6 +679,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return mailinabox.NewDNSProviderConfig(cfg)
|
||||
case "metaname":
|
||||
cfg := metaname.NewDefaultConfig()
|
||||
@ -619,6 +687,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return metaname.NewDNSProviderConfig(cfg)
|
||||
case "mydnsjp":
|
||||
cfg := mydnsjp.NewDefaultConfig()
|
||||
@ -626,6 +695,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return mydnsjp.NewDNSProviderConfig(cfg)
|
||||
case "namecheap":
|
||||
cfg := namecheap.NewDefaultConfig()
|
||||
@ -633,6 +703,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return namecheap.NewDNSProviderConfig(cfg)
|
||||
case "namedotcom":
|
||||
cfg := namedotcom.NewDefaultConfig()
|
||||
@ -640,6 +711,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return namedotcom.NewDNSProviderConfig(cfg)
|
||||
case "namesilo":
|
||||
cfg := namesilo.NewDefaultConfig()
|
||||
@ -647,6 +719,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return namesilo.NewDNSProviderConfig(cfg)
|
||||
case "nearlyfreespeech":
|
||||
cfg := nearlyfreespeech.NewDefaultConfig()
|
||||
@ -654,6 +727,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return nearlyfreespeech.NewDNSProviderConfig(cfg)
|
||||
case "netcup":
|
||||
cfg := netcup.NewDefaultConfig()
|
||||
@ -661,7 +735,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 1200 * time.Second
|
||||
cfg.PropagationTimeout = 20*time.Minute
|
||||
return netcup.NewDNSProviderConfig(cfg)
|
||||
case "netlify":
|
||||
cfg := netlify.NewDefaultConfig()
|
||||
@ -669,6 +743,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return netlify.NewDNSProviderConfig(cfg)
|
||||
case "nicmanager":
|
||||
cfg := nicmanager.NewDefaultConfig()
|
||||
@ -676,6 +751,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return nicmanager.NewDNSProviderConfig(cfg)
|
||||
case "nifcloud":
|
||||
cfg := nifcloud.NewDefaultConfig()
|
||||
@ -683,6 +759,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return nifcloud.NewDNSProviderConfig(cfg)
|
||||
case "njalla":
|
||||
cfg := njalla.NewDefaultConfig()
|
||||
@ -690,6 +767,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return njalla.NewDNSProviderConfig(cfg)
|
||||
case "nodion":
|
||||
cfg := nodion.NewDefaultConfig()
|
||||
@ -697,6 +775,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return nodion.NewDNSProviderConfig(cfg)
|
||||
case "ns1":
|
||||
cfg := ns1.NewDefaultConfig()
|
||||
@ -704,6 +783,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return ns1.NewDNSProviderConfig(cfg)
|
||||
case "otc":
|
||||
cfg := otc.NewDefaultConfig()
|
||||
@ -711,6 +791,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return otc.NewDNSProviderConfig(cfg)
|
||||
case "ovh":
|
||||
cfg := ovh.NewDefaultConfig()
|
||||
@ -718,6 +799,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return ovh.NewDNSProviderConfig(cfg)
|
||||
case "pdns":
|
||||
cfg := pdns.NewDefaultConfig()
|
||||
@ -725,6 +807,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return pdns.NewDNSProviderConfig(cfg)
|
||||
case "plesk":
|
||||
cfg := plesk.NewDefaultConfig()
|
||||
@ -732,6 +815,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return plesk.NewDNSProviderConfig(cfg)
|
||||
case "porkbun":
|
||||
cfg := porkbun.NewDefaultConfig()
|
||||
@ -739,6 +823,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return porkbun.NewDNSProviderConfig(cfg)
|
||||
case "rackspace":
|
||||
cfg := rackspace.NewDefaultConfig()
|
||||
@ -746,6 +831,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return rackspace.NewDNSProviderConfig(cfg)
|
||||
case "rcodezero":
|
||||
cfg := rcodezero.NewDefaultConfig()
|
||||
@ -753,6 +839,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return rcodezero.NewDNSProviderConfig(cfg)
|
||||
case "regru":
|
||||
cfg := regru.NewDefaultConfig()
|
||||
@ -760,6 +847,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return regru.NewDNSProviderConfig(cfg)
|
||||
case "rfc2136":
|
||||
cfg := rfc2136.NewDefaultConfig()
|
||||
@ -767,6 +855,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return rfc2136.NewDNSProviderConfig(cfg)
|
||||
case "rimuhosting":
|
||||
cfg := rimuhosting.NewDefaultConfig()
|
||||
@ -774,6 +863,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return rimuhosting.NewDNSProviderConfig(cfg)
|
||||
case "route53":
|
||||
cfg := route53.NewDefaultConfig()
|
||||
@ -781,6 +871,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return route53.NewDNSProviderConfig(cfg)
|
||||
case "safedns":
|
||||
cfg := safedns.NewDefaultConfig()
|
||||
@ -788,6 +879,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return safedns.NewDNSProviderConfig(cfg)
|
||||
case "sakuracloud":
|
||||
cfg := sakuracloud.NewDefaultConfig()
|
||||
@ -795,6 +887,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return sakuracloud.NewDNSProviderConfig(cfg)
|
||||
case "scaleway":
|
||||
cfg := scaleway.NewDefaultConfig()
|
||||
@ -802,6 +895,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return scaleway.NewDNSProviderConfig(cfg)
|
||||
case "selectel":
|
||||
cfg := selectel.NewDefaultConfig()
|
||||
@ -809,6 +903,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return selectel.NewDNSProviderConfig(cfg)
|
||||
case "servercow":
|
||||
cfg := servercow.NewDefaultConfig()
|
||||
@ -816,6 +911,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return servercow.NewDNSProviderConfig(cfg)
|
||||
case "shellrent":
|
||||
cfg := shellrent.NewDefaultConfig()
|
||||
@ -823,6 +919,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return shellrent.NewDNSProviderConfig(cfg)
|
||||
case "simply":
|
||||
cfg := simply.NewDefaultConfig()
|
||||
@ -830,6 +927,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return simply.NewDNSProviderConfig(cfg)
|
||||
case "sonic":
|
||||
cfg := sonic.NewDefaultConfig()
|
||||
@ -837,6 +935,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return sonic.NewDNSProviderConfig(cfg)
|
||||
case "stackpath":
|
||||
cfg := stackpath.NewDefaultConfig()
|
||||
@ -844,6 +943,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return stackpath.NewDNSProviderConfig(cfg)
|
||||
case "tencentcloud":
|
||||
cfg := tencentcloud.NewDefaultConfig()
|
||||
@ -851,6 +951,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return tencentcloud.NewDNSProviderConfig(cfg)
|
||||
case "transip":
|
||||
cfg := transip.NewDefaultConfig()
|
||||
@ -858,6 +959,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return transip.NewDNSProviderConfig(cfg)
|
||||
case "ultradns":
|
||||
cfg := ultradns.NewDefaultConfig()
|
||||
@ -865,6 +967,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return ultradns.NewDNSProviderConfig(cfg)
|
||||
case "variomedia":
|
||||
cfg := variomedia.NewDefaultConfig()
|
||||
@ -872,6 +975,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return variomedia.NewDNSProviderConfig(cfg)
|
||||
case "vegadns":
|
||||
cfg := vegadns.NewDefaultConfig()
|
||||
@ -879,6 +983,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return vegadns.NewDNSProviderConfig(cfg)
|
||||
case "vercel":
|
||||
cfg := vercel.NewDefaultConfig()
|
||||
@ -886,6 +991,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return vercel.NewDNSProviderConfig(cfg)
|
||||
case "versio":
|
||||
cfg := versio.NewDefaultConfig()
|
||||
@ -893,6 +999,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return versio.NewDNSProviderConfig(cfg)
|
||||
case "vinyldns":
|
||||
cfg := vinyldns.NewDefaultConfig()
|
||||
@ -900,6 +1007,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return vinyldns.NewDNSProviderConfig(cfg)
|
||||
case "vkcloud":
|
||||
cfg := vkcloud.NewDefaultConfig()
|
||||
@ -907,6 +1015,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return vkcloud.NewDNSProviderConfig(cfg)
|
||||
case "vscale":
|
||||
cfg := vscale.NewDefaultConfig()
|
||||
@ -914,6 +1023,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return vscale.NewDNSProviderConfig(cfg)
|
||||
case "vultr":
|
||||
cfg := vultr.NewDefaultConfig()
|
||||
@ -921,6 +1031,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return vultr.NewDNSProviderConfig(cfg)
|
||||
case "webnames":
|
||||
cfg := webnames.NewDefaultConfig()
|
||||
@ -928,6 +1039,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return webnames.NewDNSProviderConfig(cfg)
|
||||
case "websupport":
|
||||
cfg := websupport.NewDefaultConfig()
|
||||
@ -935,6 +1047,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return websupport.NewDNSProviderConfig(cfg)
|
||||
case "wedos":
|
||||
cfg := wedos.NewDefaultConfig()
|
||||
@ -942,6 +1055,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return wedos.NewDNSProviderConfig(cfg)
|
||||
case "yandex":
|
||||
cfg := yandex.NewDefaultConfig()
|
||||
@ -949,6 +1063,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return yandex.NewDNSProviderConfig(cfg)
|
||||
case "yandex360":
|
||||
cfg := yandex360.NewDefaultConfig()
|
||||
@ -956,6 +1071,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return yandex360.NewDNSProviderConfig(cfg)
|
||||
case "yandexcloud":
|
||||
cfg := yandexcloud.NewDefaultConfig()
|
||||
@ -963,6 +1079,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return yandexcloud.NewDNSProviderConfig(cfg)
|
||||
case "zoneee":
|
||||
cfg := zoneee.NewDefaultConfig()
|
||||
@ -970,6 +1087,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return zoneee.NewDNSProviderConfig(cfg)
|
||||
case "zonomi":
|
||||
cfg := zonomi.NewDefaultConfig()
|
||||
@ -977,6 +1095,7 @@ func GetDNSProviderByJsonConfig(name string, js string)(challenge.Provider, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return zonomi.NewDNSProviderConfig(cfg)
|
||||
default:
|
||||
return nil, fmt.Errorf("unrecognized DNS provider: %s", name)
|
||||
|
@ -153,6 +153,10 @@
|
||||
"azure": {
|
||||
"Name": "azure",
|
||||
"ConfigableFields": [
|
||||
{
|
||||
"Title": "ZoneName",
|
||||
"Datatype": "string"
|
||||
},
|
||||
{
|
||||
"Title": "ClientID",
|
||||
"Datatype": "string"
|
||||
@ -208,6 +212,10 @@
|
||||
"azuredns": {
|
||||
"Name": "azuredns",
|
||||
"ConfigableFields": [
|
||||
{
|
||||
"Title": "ZoneName",
|
||||
"Datatype": "string"
|
||||
},
|
||||
{
|
||||
"Title": "SubscriptionID",
|
||||
"Datatype": "string"
|
||||
@ -343,6 +351,10 @@
|
||||
{
|
||||
"Title": "HTTPClient",
|
||||
"Datatype": "*http.Client"
|
||||
},
|
||||
{
|
||||
"Title": "SkipDeploy",
|
||||
"Datatype": "bool"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -1214,10 +1226,6 @@
|
||||
"gandi": {
|
||||
"Name": "gandi",
|
||||
"ConfigableFields": [
|
||||
{
|
||||
"Title": "BaseURL",
|
||||
"Datatype": "string"
|
||||
},
|
||||
{
|
||||
"Title": "APIKey",
|
||||
"Datatype": "string"
|
||||
@ -1241,10 +1249,6 @@
|
||||
"gandiv5": {
|
||||
"Name": "gandiv5",
|
||||
"ConfigableFields": [
|
||||
{
|
||||
"Title": "BaseURL",
|
||||
"Datatype": "string"
|
||||
},
|
||||
{
|
||||
"Title": "APIKey",
|
||||
"Datatype": "string"
|
||||
|
@ -34,6 +34,7 @@ type AutoRenewer struct {
|
||||
AcmeHandler *ACMEHandler
|
||||
RenewerConfig *AutoRenewConfig
|
||||
RenewTickInterval int64
|
||||
EarlyRenewDays int //How many days before cert expire to renew certificate
|
||||
TickerstopChan chan bool
|
||||
}
|
||||
|
||||
@ -44,11 +45,15 @@ type ExpiredCerts struct {
|
||||
|
||||
// Create an auto renew agent, require config filepath and auto scan & renew interval (seconds)
|
||||
// Set renew check interval to 0 for auto (1 day)
|
||||
func NewAutoRenewer(config string, certFolder string, renewCheckInterval int64, AcmeHandler *ACMEHandler) (*AutoRenewer, error) {
|
||||
func NewAutoRenewer(config string, certFolder string, renewCheckInterval int64, earlyRenewDays int, AcmeHandler *ACMEHandler) (*AutoRenewer, error) {
|
||||
if renewCheckInterval == 0 {
|
||||
renewCheckInterval = 86400 //1 day
|
||||
}
|
||||
|
||||
if earlyRenewDays == 0 {
|
||||
earlyRenewDays = 30
|
||||
}
|
||||
|
||||
//Load the config file. If not found, create one
|
||||
if !utils.FileExists(config) {
|
||||
//Create one
|
||||
@ -135,7 +140,7 @@ func (a *AutoRenewer) StopAutoRenewTicker() {
|
||||
// opr = setSelected -> Enter a list of file names (or matching rules) for auto renew
|
||||
// opr = setAuto -> Set to use auto detect certificates and renew
|
||||
func (a *AutoRenewer) HandleSetAutoRenewDomains(w http.ResponseWriter, r *http.Request) {
|
||||
opr, err := utils.GetPara(r, "opr")
|
||||
opr, err := utils.PostPara(r, "opr")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "Operation not set")
|
||||
return
|
||||
@ -165,6 +170,8 @@ func (a *AutoRenewer) HandleSetAutoRenewDomains(w http.ResponseWriter, r *http.R
|
||||
a.RenewerConfig.RenewAll = true
|
||||
a.saveRenewConfigToFile()
|
||||
utils.SendOK(w)
|
||||
} else {
|
||||
utils.SendErrorResponse(w, "invalid operation given")
|
||||
}
|
||||
|
||||
}
|
||||
@ -208,19 +215,22 @@ func (a *AutoRenewer) HandleRenewNow(w http.ResponseWriter, r *http.Request) {
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
}
|
||||
|
||||
// HandleAutoRenewEnable get and set the auto renew enable state
|
||||
func (a *AutoRenewer) HandleAutoRenewEnable(w http.ResponseWriter, r *http.Request) {
|
||||
val, err := utils.PostPara(r, "enable")
|
||||
if err != nil {
|
||||
if r.Method == http.MethodGet {
|
||||
js, _ := json.Marshal(a.RenewerConfig.Enabled)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
} else {
|
||||
if val == "true" {
|
||||
} else if r.Method == http.MethodPost {
|
||||
val, err := utils.PostBool(r, "enable")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid or empty enable state")
|
||||
}
|
||||
if val {
|
||||
//Check if the email is not empty
|
||||
if a.RenewerConfig.Email == "" {
|
||||
utils.SendErrorResponse(w, "Email is not set")
|
||||
return
|
||||
}
|
||||
|
||||
a.RenewerConfig.Enabled = true
|
||||
a.saveRenewConfigToFile()
|
||||
log.Println("[ACME] ACME auto renew enabled")
|
||||
@ -231,19 +241,26 @@ func (a *AutoRenewer) HandleAutoRenewEnable(w http.ResponseWriter, r *http.Reque
|
||||
log.Println("[ACME] ACME auto renew disabled")
|
||||
a.StopAutoRenewTicker()
|
||||
}
|
||||
} else {
|
||||
http.Error(w, "405 - Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (a *AutoRenewer) HandleACMEEmail(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
email, err := utils.PostPara(r, "set")
|
||||
if err != nil {
|
||||
if r.Method == http.MethodGet {
|
||||
//Return the current email to user
|
||||
js, _ := json.Marshal(a.RenewerConfig.Email)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
} else {
|
||||
} else if r.Method == http.MethodPost {
|
||||
email, err := utils.PostPara(r, "set")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid or empty email given")
|
||||
return
|
||||
}
|
||||
|
||||
//Check if the email is valid
|
||||
_, err := mail.ParseAddress(email)
|
||||
_, err = mail.ParseAddress(email)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
@ -252,8 +269,11 @@ func (a *AutoRenewer) HandleACMEEmail(w http.ResponseWriter, r *http.Request) {
|
||||
//Set the new config
|
||||
a.RenewerConfig.Email = email
|
||||
a.saveRenewConfigToFile()
|
||||
}
|
||||
|
||||
utils.SendOK(w)
|
||||
} else {
|
||||
http.Error(w, "405 - Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
// Check and renew certificates. This check all the certificates in the
|
||||
@ -277,7 +297,7 @@ func (a *AutoRenewer) CheckAndRenewCertificates() ([]string, error) {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if CertExpireSoon(certBytes) || CertIsExpired(certBytes) {
|
||||
if CertExpireSoon(certBytes, a.EarlyRenewDays) || CertIsExpired(certBytes) {
|
||||
//This cert is expired
|
||||
|
||||
DNSName, err := ExtractDomains(certBytes)
|
||||
@ -305,7 +325,7 @@ func (a *AutoRenewer) CheckAndRenewCertificates() ([]string, error) {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if CertExpireSoon(certBytes) || CertIsExpired(certBytes) {
|
||||
if CertExpireSoon(certBytes, a.EarlyRenewDays) || CertIsExpired(certBytes) {
|
||||
//This cert is expired
|
||||
|
||||
DNSName, err := ExtractDomains(certBytes)
|
||||
|
@ -81,13 +81,14 @@ func CertIsExpired(certBytes []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func CertExpireSoon(certBytes []byte) bool {
|
||||
// CertExpireSoon check if the given cert bytes will expires within the given number of days from now
|
||||
func CertExpireSoon(certBytes []byte, numberOfDays int) bool {
|
||||
block, _ := pem.Decode(certBytes)
|
||||
if block != nil {
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err == nil {
|
||||
expirationDate := cert.NotAfter
|
||||
threshold := 14 * 24 * time.Hour // 14 days
|
||||
threshold := time.Duration(numberOfDays) * 24 * time.Hour
|
||||
|
||||
timeRemaining := time.Until(expirationDate)
|
||||
if timeRemaining <= threshold {
|
||||
|
@ -10,7 +10,7 @@ type RouterOption struct {
|
||||
AuthAgent *AuthAgent
|
||||
RequireAuth bool //This router require authentication
|
||||
DeniedHandler func(http.ResponseWriter, *http.Request) //Things to do when request is rejected
|
||||
|
||||
TargetMux *http.ServeMux
|
||||
}
|
||||
|
||||
type RouterDef struct {
|
||||
@ -35,17 +35,31 @@ func (router *RouterDef) HandleFunc(endpoint string, handler func(http.ResponseW
|
||||
authAgent := router.option.AuthAgent
|
||||
|
||||
//OK. Register handler
|
||||
http.HandleFunc(endpoint, func(w http.ResponseWriter, r *http.Request) {
|
||||
//Check authentication of the user
|
||||
if router.option.RequireAuth {
|
||||
authAgent.HandleCheckAuth(w, r, func(w http.ResponseWriter, r *http.Request) {
|
||||
if router.option.TargetMux == nil {
|
||||
http.HandleFunc(endpoint, func(w http.ResponseWriter, r *http.Request) {
|
||||
//Check authentication of the user
|
||||
if router.option.RequireAuth {
|
||||
authAgent.HandleCheckAuth(w, r, func(w http.ResponseWriter, r *http.Request) {
|
||||
handler(w, r)
|
||||
})
|
||||
} else {
|
||||
handler(w, r)
|
||||
})
|
||||
} else {
|
||||
handler(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
} else {
|
||||
router.option.TargetMux.HandleFunc(endpoint, func(w http.ResponseWriter, r *http.Request) {
|
||||
//Check authentication of the user
|
||||
if router.option.RequireAuth {
|
||||
authAgent.HandleCheckAuth(w, r, func(w http.ResponseWriter, r *http.Request) {
|
||||
handler(w, r)
|
||||
})
|
||||
} else {
|
||||
handler(w, r)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
router.endpoints[endpoint] = handler
|
||||
|
||||
|
@ -3,8 +3,6 @@
|
||||
|
||||
package dockerux
|
||||
|
||||
/* Windows docker optimizer*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
@ -16,7 +14,6 @@ import (
|
||||
"imuslab.com/zoraxy/mod/utils"
|
||||
)
|
||||
|
||||
// Windows build not support docker
|
||||
func (d *UXOptimizer) HandleDockerAvailable(w http.ResponseWriter, r *http.Request) {
|
||||
js, _ := json.Marshal(d.RunninInDocker)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
|
21
src/mod/dynamicproxy/domainsniff/proxmox.go
Normal file
21
src/mod/dynamicproxy/domainsniff/proxmox.go
Normal file
@ -0,0 +1,21 @@
|
||||
package domainsniff
|
||||
|
||||
import "net/http"
|
||||
|
||||
/*
|
||||
Promox API sniffer
|
||||
|
||||
This handler sniff proxmox API endpoint and
|
||||
adjust the request accordingly to fix shits
|
||||
in the proxmox API server
|
||||
*/
|
||||
|
||||
func IsProxmox(r *http.Request) bool {
|
||||
// Check if any of the cookies is named PVEAuthCookie
|
||||
for _, cookie := range r.Cookies() {
|
||||
if cookie.Name == "PVEAuthCookie" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"imuslab.com/zoraxy/mod/dynamicproxy/domainsniff"
|
||||
"imuslab.com/zoraxy/mod/dynamicproxy/permissionpolicy"
|
||||
)
|
||||
|
||||
@ -50,13 +51,13 @@ type ReverseProxy struct {
|
||||
ModifyResponse func(*http.Response) error
|
||||
|
||||
//Prepender is an optional prepend text for URL rewrite
|
||||
//
|
||||
Prepender string
|
||||
|
||||
Verbal bool
|
||||
}
|
||||
|
||||
type ResponseRewriteRuleSet struct {
|
||||
/* Basic Rewrite Rulesets */
|
||||
ProxyDomain string
|
||||
OriginalHost string
|
||||
UseTLS bool
|
||||
@ -64,8 +65,13 @@ type ResponseRewriteRuleSet struct {
|
||||
PathPrefix string //Vdir prefix for root, / will be rewrite to this
|
||||
UpstreamHeaders [][]string
|
||||
DownstreamHeaders [][]string
|
||||
NoRemoveHopByHop bool //Do not remove hop-by-hop headers, dangerous
|
||||
Version string //Version number of Zoraxy, use for X-Proxy-By
|
||||
|
||||
/* Advance Usecase Options */
|
||||
HostHeaderOverwrite string //Force overwrite of request "Host" header (advanced usecase)
|
||||
NoRemoveHopByHop bool //Do not remove hop-by-hop headers (advanced usecase)
|
||||
|
||||
/* System Information Payload */
|
||||
Version string //Version number of Zoraxy, use for X-Proxy-By
|
||||
}
|
||||
|
||||
type requestCanceler interface {
|
||||
@ -73,8 +79,8 @@ type requestCanceler interface {
|
||||
}
|
||||
|
||||
type DpcoreOptions struct {
|
||||
IgnoreTLSVerification bool
|
||||
FlushInterval time.Duration
|
||||
IgnoreTLSVerification bool //Disable all TLS verification when request pass through this proxy router
|
||||
FlushInterval time.Duration //Duration to flush in normal requests. Stream request or keep-alive request will always flush with interval of -1 (immediately)
|
||||
}
|
||||
|
||||
func NewDynamicProxyCore(target *url.URL, prepender string, dpcOptions *DpcoreOptions) *ReverseProxy {
|
||||
@ -252,7 +258,7 @@ func (p *ReverseProxy) logf(format string, args ...interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr *ResponseRewriteRuleSet) error {
|
||||
func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr *ResponseRewriteRuleSet) (int, error) {
|
||||
transport := p.Transport
|
||||
|
||||
outreq := new(http.Request)
|
||||
@ -281,7 +287,10 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr
|
||||
outreq.Close = false
|
||||
|
||||
//Only skip origin rewrite iff proxy target require TLS and it is external domain name like github.com
|
||||
if !(rrr.UseTLS && isExternalDomainName(rrr.ProxyDomain)) {
|
||||
if rrr.HostHeaderOverwrite != "" {
|
||||
//Use user defined overwrite header value, see issue #255
|
||||
outreq.Host = rrr.HostHeaderOverwrite
|
||||
} else if !(rrr.UseTLS && isExternalDomainName(rrr.ProxyDomain)) {
|
||||
// Always use the original host, see issue #164
|
||||
outreq.Host = rrr.OriginalHost
|
||||
}
|
||||
@ -291,7 +300,9 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr
|
||||
copyHeader(outreq.Header, req.Header)
|
||||
|
||||
// Remove hop-by-hop headers.
|
||||
removeHeaders(outreq.Header, rrr.NoCache)
|
||||
if !rrr.NoRemoveHopByHop {
|
||||
removeHeaders(outreq.Header, rrr.NoCache)
|
||||
}
|
||||
|
||||
// Add X-Forwarded-For Header.
|
||||
addXForwardedForHeader(outreq)
|
||||
@ -302,6 +313,11 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr
|
||||
// Rewrite outbound UA, must be after user headers
|
||||
rewriteUserAgent(outreq.Header, "Zoraxy/"+rrr.Version)
|
||||
|
||||
//Fix proxmox transfer encoding bug if detected Proxmox Cookie
|
||||
if domainsniff.IsProxmox(req) {
|
||||
outreq.TransferEncoding = []string{"identity"}
|
||||
}
|
||||
|
||||
res, err := transport.RoundTrip(outreq)
|
||||
if err != nil {
|
||||
if p.Verbal {
|
||||
@ -309,11 +325,13 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr
|
||||
}
|
||||
|
||||
//rw.WriteHeader(http.StatusBadGateway)
|
||||
return err
|
||||
return http.StatusBadGateway, err
|
||||
}
|
||||
|
||||
// Remove hop-by-hop headers listed in the "Connection" header of the response, Remove hop-by-hop headers.
|
||||
removeHeaders(res.Header, rrr.NoCache)
|
||||
if !rrr.NoRemoveHopByHop {
|
||||
removeHeaders(res.Header, rrr.NoCache)
|
||||
}
|
||||
|
||||
//Remove the User-Agent header if exists
|
||||
if _, ok := res.Header["User-Agent"]; ok {
|
||||
@ -328,7 +346,7 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr
|
||||
}
|
||||
|
||||
//rw.WriteHeader(http.StatusBadGateway)
|
||||
return err
|
||||
return http.StatusBadGateway, err
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,7 +393,6 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr
|
||||
copyHeader(rw.Header(), res.Header)
|
||||
|
||||
// inject permission policy headers
|
||||
//TODO: Load permission policy from rrr
|
||||
permissionpolicy.InjectPermissionPolicyHeader(rw, nil)
|
||||
|
||||
// The "Trailer" header isn't included in the Transport's response, Build it up from Trailer.
|
||||
@ -405,14 +422,14 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr
|
||||
res.Body.Close()
|
||||
copyHeader(rw.Header(), res.Trailer)
|
||||
|
||||
return nil
|
||||
return res.StatusCode, nil
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) ProxyHTTPS(rw http.ResponseWriter, req *http.Request) error {
|
||||
func (p *ReverseProxy) ProxyHTTPS(rw http.ResponseWriter, req *http.Request) (int, error) {
|
||||
hij, ok := rw.(http.Hijacker)
|
||||
if !ok {
|
||||
p.logf("http server does not support hijacker")
|
||||
return errors.New("http server does not support hijacker")
|
||||
return http.StatusNotImplemented, errors.New("http server does not support hijacker")
|
||||
}
|
||||
|
||||
clientConn, _, err := hij.Hijack()
|
||||
@ -420,7 +437,7 @@ func (p *ReverseProxy) ProxyHTTPS(rw http.ResponseWriter, req *http.Request) err
|
||||
if p.Verbal {
|
||||
p.logf("http: proxy error: %v", err)
|
||||
}
|
||||
return err
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
proxyConn, err := net.Dial("tcp", req.URL.Host)
|
||||
@ -429,7 +446,7 @@ func (p *ReverseProxy) ProxyHTTPS(rw http.ResponseWriter, req *http.Request) err
|
||||
p.logf("http: proxy error: %v", err)
|
||||
}
|
||||
|
||||
return err
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
// The returned net.Conn may have read or write deadlines
|
||||
@ -448,7 +465,7 @@ func (p *ReverseProxy) ProxyHTTPS(rw http.ResponseWriter, req *http.Request) err
|
||||
if p.Verbal {
|
||||
p.logf("http: proxy error: %v", err)
|
||||
}
|
||||
return err
|
||||
return http.StatusGatewayTimeout, err
|
||||
}
|
||||
|
||||
err = proxyConn.SetDeadline(deadline)
|
||||
@ -457,7 +474,7 @@ func (p *ReverseProxy) ProxyHTTPS(rw http.ResponseWriter, req *http.Request) err
|
||||
p.logf("http: proxy error: %v", err)
|
||||
}
|
||||
|
||||
return err
|
||||
return http.StatusGatewayTimeout, err
|
||||
}
|
||||
|
||||
_, err = clientConn.Write([]byte("HTTP/1.0 200 OK\r\n\r\n"))
|
||||
@ -466,7 +483,7 @@ func (p *ReverseProxy) ProxyHTTPS(rw http.ResponseWriter, req *http.Request) err
|
||||
p.logf("http: proxy error: %v", err)
|
||||
}
|
||||
|
||||
return err
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
@ -479,15 +496,13 @@ func (p *ReverseProxy) ProxyHTTPS(rw http.ResponseWriter, req *http.Request) err
|
||||
proxyConn.Close()
|
||||
clientConn.Close()
|
||||
|
||||
return nil
|
||||
return http.StatusOK, nil
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request, rrr *ResponseRewriteRuleSet) error {
|
||||
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request, rrr *ResponseRewriteRuleSet) (int, error) {
|
||||
if req.Method == "CONNECT" {
|
||||
err := p.ProxyHTTPS(rw, req)
|
||||
return err
|
||||
return p.ProxyHTTPS(rw, req)
|
||||
} else {
|
||||
err := p.ProxyHTTP(rw, req, rrr)
|
||||
return err
|
||||
return p.ProxyHTTP(rw, req, rrr)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
package dpcore
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
@ -92,3 +95,63 @@ func isExternalDomainName(hostname string) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// DeepCopyRequest returns a deep copy of the given http.Request.
|
||||
func DeepCopyRequest(req *http.Request) (*http.Request, error) {
|
||||
// Copy the URL
|
||||
urlCopy := *req.URL
|
||||
|
||||
// Copy the headers
|
||||
headersCopy := make(http.Header, len(req.Header))
|
||||
for k, vv := range req.Header {
|
||||
vvCopy := make([]string, len(vv))
|
||||
copy(vvCopy, vv)
|
||||
headersCopy[k] = vvCopy
|
||||
}
|
||||
|
||||
// Copy the cookies
|
||||
cookiesCopy := make([]*http.Cookie, len(req.Cookies()))
|
||||
for i, cookie := range req.Cookies() {
|
||||
cookieCopy := *cookie
|
||||
cookiesCopy[i] = &cookieCopy
|
||||
}
|
||||
|
||||
// Copy the body, if present
|
||||
var bodyCopy io.ReadCloser
|
||||
if req.Body != nil {
|
||||
var buf bytes.Buffer
|
||||
if _, err := buf.ReadFrom(req.Body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Reset the request body so it can be read again
|
||||
if err := req.Body.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Body = io.NopCloser(&buf)
|
||||
bodyCopy = io.NopCloser(bytes.NewReader(buf.Bytes()))
|
||||
}
|
||||
|
||||
// Create the new request
|
||||
reqCopy := &http.Request{
|
||||
Method: req.Method,
|
||||
URL: &urlCopy,
|
||||
Proto: req.Proto,
|
||||
ProtoMajor: req.ProtoMajor,
|
||||
ProtoMinor: req.ProtoMinor,
|
||||
Header: headersCopy,
|
||||
Body: bodyCopy,
|
||||
ContentLength: req.ContentLength,
|
||||
TransferEncoding: append([]string(nil), req.TransferEncoding...),
|
||||
Close: req.Close,
|
||||
Host: req.Host,
|
||||
Form: req.Form,
|
||||
PostForm: req.PostForm,
|
||||
MultipartForm: req.MultipartForm,
|
||||
Trailer: req.Trailer,
|
||||
RemoteAddr: req.RemoteAddr,
|
||||
TLS: req.TLS,
|
||||
// Cancel and Context are not copied as it might cause issues
|
||||
}
|
||||
|
||||
return reqCopy, nil
|
||||
}
|
||||
|
@ -158,12 +158,13 @@ func (router *Router) StartProxyService() error {
|
||||
router.logRequest(r, false, 404, "vdir-http", r.Host)
|
||||
}
|
||||
selectedUpstream.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{
|
||||
ProxyDomain: selectedUpstream.OriginIpOrDomain,
|
||||
OriginalHost: originalHostHeader,
|
||||
UseTLS: selectedUpstream.RequireTLS,
|
||||
NoRemoveHopByHop: sep.DisableHopByHopHeaderRemoval,
|
||||
PathPrefix: "",
|
||||
Version: sep.parent.Option.HostVersion,
|
||||
ProxyDomain: selectedUpstream.OriginIpOrDomain,
|
||||
OriginalHost: originalHostHeader,
|
||||
UseTLS: selectedUpstream.RequireTLS,
|
||||
HostHeaderOverwrite: sep.RequestHostOverwrite,
|
||||
NoRemoveHopByHop: sep.DisableHopByHopHeaderRemoval,
|
||||
PathPrefix: "",
|
||||
Version: sep.parent.Option.HostVersion,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
@ -61,8 +61,8 @@ func (u *Upstream) Clone() *Upstream {
|
||||
return &newUpstream
|
||||
}
|
||||
|
||||
// ServeHTTP uses this upstream proxy router to route the current request
|
||||
func (u *Upstream) ServeHTTP(w http.ResponseWriter, r *http.Request, rrr *dpcore.ResponseRewriteRuleSet) error {
|
||||
// ServeHTTP uses this upstream proxy router to route the current request, return the status code and error if any
|
||||
func (u *Upstream) ServeHTTP(w http.ResponseWriter, r *http.Request, rrr *dpcore.ResponseRewriteRuleSet) (int, error) {
|
||||
//Auto rewrite to upstream origin if not set
|
||||
if rrr.ProxyDomain == "" {
|
||||
rrr.ProxyDomain = u.OriginIpOrDomain
|
||||
|
@ -112,6 +112,8 @@ func (router *Router) rewriteURL(rooturl string, requestURL string) string {
|
||||
func (h *ProxyHandler) hostRequest(w http.ResponseWriter, r *http.Request, target *ProxyEndpoint) {
|
||||
r.Header.Set("X-Forwarded-Host", r.Host)
|
||||
r.Header.Set("X-Forwarded-Server", "zoraxy-"+h.Parent.Option.HostUUID)
|
||||
|
||||
/* Load balancing */
|
||||
selectedUpstream, err := h.Parent.loadBalancer.GetRequestUpstreamTarget(w, r, target.ActiveOrigins, target.UseStickySession)
|
||||
if err != nil {
|
||||
http.ServeFile(w, r, "./web/rperror.html")
|
||||
@ -119,6 +121,8 @@ func (h *ProxyHandler) hostRequest(w http.ResponseWriter, r *http.Request, targe
|
||||
h.Parent.logRequest(r, false, 521, "subdomain-http", r.URL.Hostname())
|
||||
return
|
||||
}
|
||||
|
||||
/* WebSocket automatic proxy */
|
||||
requestURL := r.URL.String()
|
||||
if r.Header["Upgrade"] != nil && strings.ToLower(r.Header["Upgrade"][0]) == "websocket" {
|
||||
//Handle WebSocket request. Forward the custom Upgrade header and rewrite origin
|
||||
@ -156,16 +160,17 @@ func (h *ProxyHandler) hostRequest(w http.ResponseWriter, r *http.Request, targe
|
||||
//Build downstream and upstream header rules
|
||||
upstreamHeaders, downstreamHeaders := target.SplitInboundOutboundHeaders()
|
||||
|
||||
err = selectedUpstream.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{
|
||||
ProxyDomain: selectedUpstream.OriginIpOrDomain,
|
||||
OriginalHost: originalHostHeader,
|
||||
UseTLS: selectedUpstream.RequireTLS,
|
||||
NoCache: h.Parent.Option.NoCache,
|
||||
PathPrefix: "",
|
||||
UpstreamHeaders: upstreamHeaders,
|
||||
DownstreamHeaders: downstreamHeaders,
|
||||
NoRemoveHopByHop: target.DisableHopByHopHeaderRemoval,
|
||||
Version: target.parent.Option.HostVersion,
|
||||
statusCode, err := selectedUpstream.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{
|
||||
ProxyDomain: selectedUpstream.OriginIpOrDomain,
|
||||
OriginalHost: originalHostHeader,
|
||||
UseTLS: selectedUpstream.RequireTLS,
|
||||
NoCache: h.Parent.Option.NoCache,
|
||||
PathPrefix: "",
|
||||
UpstreamHeaders: upstreamHeaders,
|
||||
DownstreamHeaders: downstreamHeaders,
|
||||
HostHeaderOverwrite: target.RequestHostOverwrite,
|
||||
NoRemoveHopByHop: target.DisableHopByHopHeaderRemoval,
|
||||
Version: target.parent.Option.HostVersion,
|
||||
})
|
||||
|
||||
var dnsError *net.DNSError
|
||||
@ -181,7 +186,7 @@ func (h *ProxyHandler) hostRequest(w http.ResponseWriter, r *http.Request, targe
|
||||
}
|
||||
}
|
||||
|
||||
h.Parent.logRequest(r, true, 200, "host-http", r.URL.Hostname())
|
||||
h.Parent.logRequest(r, true, statusCode, "host-http", r.URL.Hostname())
|
||||
}
|
||||
|
||||
// Handle vdir type request
|
||||
@ -223,14 +228,15 @@ func (h *ProxyHandler) vdirRequest(w http.ResponseWriter, r *http.Request, targe
|
||||
//Build downstream and upstream header rules
|
||||
upstreamHeaders, downstreamHeaders := target.parent.SplitInboundOutboundHeaders()
|
||||
|
||||
err := target.proxy.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{
|
||||
ProxyDomain: target.Domain,
|
||||
OriginalHost: originalHostHeader,
|
||||
UseTLS: target.RequireTLS,
|
||||
PathPrefix: target.MatchingPath,
|
||||
UpstreamHeaders: upstreamHeaders,
|
||||
DownstreamHeaders: downstreamHeaders,
|
||||
Version: target.parent.parent.Option.HostVersion,
|
||||
statusCode, err := target.proxy.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{
|
||||
ProxyDomain: target.Domain,
|
||||
OriginalHost: originalHostHeader,
|
||||
UseTLS: target.RequireTLS,
|
||||
PathPrefix: target.MatchingPath,
|
||||
UpstreamHeaders: upstreamHeaders,
|
||||
DownstreamHeaders: downstreamHeaders,
|
||||
HostHeaderOverwrite: target.parent.RequestHostOverwrite,
|
||||
Version: target.parent.parent.Option.HostVersion,
|
||||
})
|
||||
|
||||
var dnsError *net.DNSError
|
||||
@ -245,7 +251,7 @@ func (h *ProxyHandler) vdirRequest(w http.ResponseWriter, r *http.Request, targe
|
||||
h.Parent.logRequest(r, false, 521, "vdir-http", target.Domain)
|
||||
}
|
||||
}
|
||||
h.Parent.logRequest(r, true, 200, "vdir-http", target.Domain)
|
||||
h.Parent.logRequest(r, true, statusCode, "vdir-http", target.Domain)
|
||||
|
||||
}
|
||||
|
||||
|
@ -132,10 +132,11 @@ type ProxyEndpoint struct {
|
||||
|
||||
//Custom Headers
|
||||
UserDefinedHeaders []*UserDefinedHeader //Custom headers to append when proxying requests from this endpoint
|
||||
RequestHostOverwrite string //If not empty, this domain will be used to overwrite the Host field in request header
|
||||
HSTSMaxAge int64 //HSTS max age, set to 0 for disable HSTS headers
|
||||
EnablePermissionPolicyHeader bool //Enable injection of permission policy header
|
||||
PermissionPolicy *permissionpolicy.PermissionsPolicy //Permission policy header
|
||||
DisableHopByHopHeaderRemoval bool //TODO: Do not remove hop-by-hop headers
|
||||
DisableHopByHopHeaderRemoval bool //Do not remove hop-by-hop headers
|
||||
|
||||
//Authentication
|
||||
RequireBasicAuth bool //Set to true to request basic auth before proxy
|
||||
|
@ -19,9 +19,8 @@ type Store struct {
|
||||
geodbIpv6 [][]string //Parsed geodb list for ipv6
|
||||
geotrie *trie
|
||||
geotrieIpv6 *trie
|
||||
//geoipCache sync.Map
|
||||
sysdb *database.Database
|
||||
option *StoreOptions
|
||||
sysdb *database.Database
|
||||
option *StoreOptions
|
||||
}
|
||||
|
||||
type StoreOptions struct {
|
||||
|
@ -43,7 +43,7 @@ func TestResolveCountryCodeFromIP(t *testing.T) {
|
||||
// Create a new store
|
||||
store, err := geodb.NewGeoDb(nil, &geodb.StoreOptions{
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("error creating store: %v", err)
|
||||
@ -56,6 +56,7 @@ func TestResolveCountryCodeFromIP(t *testing.T) {
|
||||
{"176.113.115.113", "RU"},
|
||||
{"65.21.233.213", "FI"},
|
||||
{"94.23.207.193", "FR"},
|
||||
{"77.131.21.232", "FR"},
|
||||
}
|
||||
|
||||
for _, testcase := range knownIpCountryMap {
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -16,13 +16,6 @@ func (s *Store) search(ip string) string {
|
||||
ip = strings.Split(ip, ",")[0]
|
||||
ip = strings.TrimSpace(ip)
|
||||
}
|
||||
//See if there are cached country code for this ip
|
||||
/*
|
||||
ccc, ok := s.geoipCache.Load(ip)
|
||||
if ok {
|
||||
return ccc.(string)
|
||||
}
|
||||
*/
|
||||
|
||||
//Search in geotrie tree
|
||||
cc := ""
|
||||
|
@ -1,7 +1,6 @@
|
||||
package geodb
|
||||
|
||||
import (
|
||||
"math"
|
||||
"net"
|
||||
)
|
||||
|
||||
@ -41,14 +40,10 @@ func (t *trie) insert(ipAddr string, cc string) {
|
||||
ipBytes := ipToBytes(ipAddr)
|
||||
current := t.root
|
||||
for _, b := range ipBytes {
|
||||
//For each byte in the ip address
|
||||
//For each byte in the ip address (4 / 16 bytes)
|
||||
//each byte is 8 bit
|
||||
for j := 0; j < 8; j++ {
|
||||
bitwise := (b&uint8(math.Pow(float64(2), float64(j))) > 0)
|
||||
bit := 0b0000
|
||||
if bitwise {
|
||||
bit = 0b0001
|
||||
}
|
||||
for j := 7; j >= 0; j-- {
|
||||
bit := int(b >> j & 1)
|
||||
if current.childrens[bit] == nil {
|
||||
current.childrens[bit] = &trie_Node{
|
||||
childrens: [2]*trie_Node{},
|
||||
@ -58,21 +53,9 @@ func (t *trie) insert(ipAddr string, cc string) {
|
||||
current = current.childrens[bit]
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for i := 63; i >= 0; i-- {
|
||||
bit := (ipInt64 >> uint(i)) & 1
|
||||
if current.childrens[bit] == nil {
|
||||
current.childrens[bit] = &trie_Node{
|
||||
childrens: [2]*trie_Node{},
|
||||
cc: cc,
|
||||
}
|
||||
}
|
||||
current = current.childrens[bit]
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// isReservedIP check if the given ip address is NOT a public ip address
|
||||
func isReservedIP(ip string) bool {
|
||||
parsedIP := net.ParseIP(ip)
|
||||
if parsedIP == nil {
|
||||
@ -86,12 +69,10 @@ func isReservedIP(ip string) bool {
|
||||
if parsedIP.IsLinkLocalUnicast() || parsedIP.IsLinkLocalMulticast() {
|
||||
return true
|
||||
}
|
||||
|
||||
//Check if the IP is in the reserved private range
|
||||
if parsedIP.IsPrivate() {
|
||||
return true
|
||||
}
|
||||
|
||||
// If the IP address is not a reserved address, return false
|
||||
return false
|
||||
}
|
||||
|
||||
@ -106,27 +87,15 @@ func (t *trie) search(ipAddr string) string {
|
||||
for _, b := range ipBytes {
|
||||
//For each byte in the ip address
|
||||
//each byte is 8 bit
|
||||
for j := 0; j < 8; j++ {
|
||||
bitwise := (b&uint8(math.Pow(float64(2), float64(j))) > 0)
|
||||
bit := 0b0000
|
||||
if bitwise {
|
||||
bit = 0b0001
|
||||
}
|
||||
for j := 7; j >= 0; j-- {
|
||||
bit := int(b >> j & 1)
|
||||
if current.childrens[bit] == nil {
|
||||
return current.cc
|
||||
}
|
||||
current = current.childrens[bit]
|
||||
}
|
||||
}
|
||||
/*
|
||||
for i := 63; i >= 0; i-- {
|
||||
bit := (ipInt64 >> uint(i)) & 1
|
||||
if current.childrens[bit] == nil {
|
||||
return current.cc
|
||||
}
|
||||
current = current.childrens[bit]
|
||||
}
|
||||
*/
|
||||
|
||||
if len(current.childrens) == 0 {
|
||||
return current.cc
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"imuslab.com/zoraxy/mod/info/logger"
|
||||
"imuslab.com/zoraxy/mod/utils"
|
||||
)
|
||||
|
||||
@ -21,15 +22,16 @@ type CertCache struct {
|
||||
}
|
||||
|
||||
type Manager struct {
|
||||
CertStore string //Path where all the certs are stored
|
||||
LoadedCerts []*CertCache //A list of loaded certs
|
||||
CertStore string //Path where all the certs are stored
|
||||
LoadedCerts []*CertCache //A list of loaded certs
|
||||
Logger *logger.Logger //System wide logger for debug mesage
|
||||
verbal bool
|
||||
}
|
||||
|
||||
//go:embed localhost.pem localhost.key
|
||||
var buildinCertStore embed.FS
|
||||
|
||||
func NewManager(certStore string, verbal bool) (*Manager, error) {
|
||||
func NewManager(certStore string, verbal bool, logger *logger.Logger) (*Manager, error) {
|
||||
if !utils.FileExists(certStore) {
|
||||
os.MkdirAll(certStore, 0775)
|
||||
}
|
||||
@ -52,6 +54,7 @@ func NewManager(certStore string, verbal bool) (*Manager, error) {
|
||||
CertStore: certStore,
|
||||
LoadedCerts: []*CertCache{},
|
||||
verbal: verbal,
|
||||
Logger: logger,
|
||||
}
|
||||
|
||||
err := thisManager.UpdateLoadedCertList()
|
||||
@ -78,7 +81,7 @@ func (m *Manager) UpdateLoadedCertList() error {
|
||||
priKey := filepath.Join(m.CertStore, certname+".key")
|
||||
certificate, err := tls.LoadX509KeyPair(pubKey, priKey)
|
||||
if err != nil {
|
||||
log.Println("Certificate loaded failed: " + certname)
|
||||
m.Logger.PrintAndLog("tls-router", "Certificate load failed: "+certname, err)
|
||||
continue
|
||||
}
|
||||
|
||||
@ -86,6 +89,7 @@ func (m *Manager) UpdateLoadedCertList() error {
|
||||
loadedCert, err := x509.ParseCertificate(thisCert)
|
||||
if err != nil {
|
||||
//Error pasring cert, skip this byte segment
|
||||
m.Logger.PrintAndLog("tls-router", "Certificate parse failed: "+certname, err)
|
||||
continue
|
||||
}
|
||||
|
||||
@ -171,37 +175,10 @@ func (m *Manager) GetCert(helloInfo *tls.ClientHelloInfo) (*tls.Certificate, err
|
||||
pubKey, priKey = m.GetCertByX509CNHostname(helloInfo.ServerName)
|
||||
} else {
|
||||
//Fallback to legacy method of matching certificates
|
||||
/*
|
||||
domainCerts, _ := m.ListCertDomains()
|
||||
cloestDomainCert := matchClosestDomainCertificate(helloInfo.ServerName, domainCerts)
|
||||
if cloestDomainCert != "" {
|
||||
//There is a matching parent domain for this subdomain. Use this instead.
|
||||
pubKey = filepath.Join(m.CertStore, cloestDomainCert+".pem")
|
||||
priKey = filepath.Join(m.CertStore, cloestDomainCert+".key")
|
||||
} else if m.DefaultCertExists() {
|
||||
//Use default.pem and default.key
|
||||
pubKey = filepath.Join(m.CertStore, "default.pem")
|
||||
priKey = filepath.Join(m.CertStore, "default.key")
|
||||
if m.verbal {
|
||||
log.Println("No matching certificate found. Serving with default")
|
||||
}
|
||||
} else {
|
||||
if m.verbal {
|
||||
log.Println("Matching certificate not found. Serving with build-in certificate. Requesting server name: ", helloInfo.ServerName)
|
||||
}
|
||||
}*/
|
||||
|
||||
if m.DefaultCertExists() {
|
||||
//Use default.pem and default.key
|
||||
pubKey = filepath.Join(m.CertStore, "default.pem")
|
||||
priKey = filepath.Join(m.CertStore, "default.key")
|
||||
//if m.verbal {
|
||||
// log.Println("No matching certificate found. Serving with default")
|
||||
//}
|
||||
} else {
|
||||
//if m.verbal {
|
||||
// log.Println("Matching certificate not found. Serving with build-in certificate. Requesting server name: ", helloInfo.ServerName)
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,7 @@ func (fm *FileManager) HandleDownload(w http.ResponseWriter, r *http.Request) {
|
||||
// HandleNewFolder creates a new folder in the specified directory
|
||||
func (fm *FileManager) HandleNewFolder(w http.ResponseWriter, r *http.Request) {
|
||||
// Parse the directory name from the request
|
||||
dirName, err := utils.GetPara(r, "path")
|
||||
dirName, err := utils.PostPara(r, "path")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid directory name")
|
||||
return
|
||||
@ -268,13 +268,13 @@ func (fm *FileManager) HandleFileCopy(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (fm *FileManager) HandleFileMove(w http.ResponseWriter, r *http.Request) {
|
||||
// Parse the source and destination paths from the request
|
||||
srcPath, err := utils.GetPara(r, "srcpath")
|
||||
srcPath, err := utils.PostPara(r, "srcpath")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid source path")
|
||||
return
|
||||
}
|
||||
|
||||
destPath, err := utils.GetPara(r, "destpath")
|
||||
destPath, err := utils.PostPara(r, "destpath")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid destination path")
|
||||
return
|
||||
|
@ -509,6 +509,9 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||
//Save it to file
|
||||
SaveReverseProxyConfig(newProxyEndpoint)
|
||||
|
||||
//Update uptime monitor targets
|
||||
UpdateUptimeMonitorTargets()
|
||||
|
||||
utils.SendOK(w)
|
||||
}
|
||||
|
||||
@ -569,7 +572,7 @@ func ReverseProxyHandleAlias(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func DeleteProxyEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||
ep, err := utils.GetPara(r, "ep")
|
||||
ep, err := utils.PostPara(r, "ep")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "Invalid ep given")
|
||||
return
|
||||
@ -589,12 +592,6 @@ func DeleteProxyEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
//Update utm if exists
|
||||
if uptimeMonitor != nil {
|
||||
uptimeMonitor.Config.Targets = GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter)
|
||||
uptimeMonitor.CleanRecords()
|
||||
}
|
||||
|
||||
//Update uptime monitor
|
||||
UpdateUptimeMonitorTargets()
|
||||
|
||||
@ -944,18 +941,22 @@ 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 {
|
||||
if r.Method == http.MethodGet {
|
||||
//Load the current status
|
||||
currentEnabled := false
|
||||
err = sysdb.Read("settings", "listenP80", ¤tEnabled)
|
||||
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 {
|
||||
} else if r.Method == http.MethodPost {
|
||||
enabled, err := utils.PostPara(r, "enable")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "enable state not set")
|
||||
return
|
||||
}
|
||||
if enabled == "true" {
|
||||
sysdb.Write("settings", "listenP80", true)
|
||||
SystemWideLogger.Println("Enabling port 80 listener")
|
||||
@ -968,38 +969,48 @@ func HandleUpdatePort80Listener(w http.ResponseWriter, r *http.Request) {
|
||||
utils.SendErrorResponse(w, "invalid mode given: "+enabled)
|
||||
}
|
||||
utils.SendOK(w)
|
||||
} else {
|
||||
http.Error(w, "405 - Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Handle https redirect
|
||||
func HandleUpdateHttpsRedirect(w http.ResponseWriter, r *http.Request) {
|
||||
useRedirect, err := utils.GetPara(r, "set")
|
||||
if err != nil {
|
||||
if r.Method == http.MethodGet {
|
||||
currentRedirectToHttps := false
|
||||
//Load the current status
|
||||
err = sysdb.Read("settings", "redirect", ¤tRedirectToHttps)
|
||||
err := sysdb.Read("settings", "redirect", ¤tRedirectToHttps)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
js, _ := json.Marshal(currentRedirectToHttps)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
} else {
|
||||
} else if r.Method == http.MethodPost {
|
||||
useRedirect, err := utils.PostBool(r, "set")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "status not set")
|
||||
return
|
||||
}
|
||||
|
||||
if dynamicProxyRouter.Option.Port == 80 {
|
||||
utils.SendErrorResponse(w, "This option is not available when listening on port 80")
|
||||
return
|
||||
}
|
||||
if useRedirect == "true" {
|
||||
if useRedirect {
|
||||
sysdb.Write("settings", "redirect", true)
|
||||
SystemWideLogger.Println("Updating force HTTPS redirection to true")
|
||||
dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(true)
|
||||
} else if useRedirect == "false" {
|
||||
} else {
|
||||
sysdb.Write("settings", "redirect", false)
|
||||
SystemWideLogger.Println("Updating force HTTPS redirection to false")
|
||||
dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(false)
|
||||
}
|
||||
|
||||
utils.SendOK(w)
|
||||
} else {
|
||||
http.Error(w, "405 - Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1089,13 +1100,13 @@ func HandleIncomingPortSet(w http.ResponseWriter, r *http.Request) {
|
||||
//List all the custom header defined in this proxy rule
|
||||
|
||||
func HandleCustomHeaderList(w http.ResponseWriter, r *http.Request) {
|
||||
epType, err := utils.PostPara(r, "type")
|
||||
epType, err := utils.GetPara(r, "type")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "endpoint type not defined")
|
||||
return
|
||||
}
|
||||
|
||||
domain, err := utils.PostPara(r, "domain")
|
||||
domain, err := utils.GetPara(r, "domain")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "domain or matching rule not defined")
|
||||
return
|
||||
@ -1238,6 +1249,150 @@ func HandleCustomHeaderRemove(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
}
|
||||
|
||||
func HandleHostOverwrite(w http.ResponseWriter, r *http.Request) {
|
||||
domain, err := utils.PostPara(r, "domain")
|
||||
if err != nil {
|
||||
domain, err = utils.GetPara(r, "domain")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "domain or matching rule not defined")
|
||||
return
|
||||
}
|
||||
}
|
||||
//Get the proxy endpoint object dedicated to this domain
|
||||
targetProxyEndpoint, err := dynamicProxyRouter.LoadProxy(domain)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "target endpoint not exists")
|
||||
return
|
||||
}
|
||||
|
||||
if r.Method == http.MethodGet {
|
||||
//Get the current host header
|
||||
js, _ := json.Marshal(targetProxyEndpoint.RequestHostOverwrite)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
} else if r.Method == http.MethodPost {
|
||||
//Set the new host header
|
||||
newHostname, _ := utils.PostPara(r, "hostname")
|
||||
|
||||
//As this will require change in the proxy instance we are running
|
||||
//we need to clone and respawn this proxy endpoint
|
||||
newProxyEndpoint := targetProxyEndpoint.Clone()
|
||||
newProxyEndpoint.RequestHostOverwrite = newHostname
|
||||
//Save proxy endpoint
|
||||
err = SaveReverseProxyConfig(newProxyEndpoint)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
//Spawn a new endpoint with updated dpcore
|
||||
preparedEndpoint, err := dynamicProxyRouter.PrepareProxyRoute(newProxyEndpoint)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
//Remove the old endpoint
|
||||
err = targetProxyEndpoint.Remove()
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
//Add the newly prepared endpoint to runtime
|
||||
err = dynamicProxyRouter.AddProxyRouteToRuntime(preparedEndpoint)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
//Print log message
|
||||
if newHostname != "" {
|
||||
SystemWideLogger.Println("Updated " + domain + " hostname overwrite to: " + newHostname)
|
||||
} else {
|
||||
SystemWideLogger.Println("Removed " + domain + " hostname overwrite")
|
||||
}
|
||||
|
||||
utils.SendOK(w)
|
||||
} else {
|
||||
//Invalid method
|
||||
http.Error(w, "405 - Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
// HandleHopByHop get and set the hop by hop remover state
|
||||
// note that it shows the DISABLE STATE of hop-by-hop remover, not the enable state
|
||||
func HandleHopByHop(w http.ResponseWriter, r *http.Request) {
|
||||
domain, err := utils.PostPara(r, "domain")
|
||||
if err != nil {
|
||||
domain, err = utils.GetPara(r, "domain")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "domain or matching rule not defined")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
targetProxyEndpoint, err := dynamicProxyRouter.LoadProxy(domain)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "target endpoint not exists")
|
||||
return
|
||||
}
|
||||
|
||||
if r.Method == http.MethodGet {
|
||||
//Get the current hop by hop header state
|
||||
js, _ := json.Marshal(!targetProxyEndpoint.DisableHopByHopHeaderRemoval)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
} else if r.Method == http.MethodPost {
|
||||
//Set the hop by hop header state
|
||||
enableHopByHopRemover, _ := utils.PostBool(r, "removeHopByHop")
|
||||
|
||||
//As this will require change in the proxy instance we are running
|
||||
//we need to clone and respawn this proxy endpoint
|
||||
newProxyEndpoint := targetProxyEndpoint.Clone()
|
||||
//Storage file use false as default, so disable removal = not enable remover
|
||||
newProxyEndpoint.DisableHopByHopHeaderRemoval = !enableHopByHopRemover
|
||||
|
||||
//Save proxy endpoint
|
||||
err = SaveReverseProxyConfig(newProxyEndpoint)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
//Spawn a new endpoint with updated dpcore
|
||||
preparedEndpoint, err := dynamicProxyRouter.PrepareProxyRoute(newProxyEndpoint)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
//Remove the old endpoint
|
||||
err = targetProxyEndpoint.Remove()
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
//Add the newly prepared endpoint to runtime
|
||||
err = dynamicProxyRouter.AddProxyRouteToRuntime(preparedEndpoint)
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
//Print log message
|
||||
if enableHopByHopRemover {
|
||||
SystemWideLogger.Println("Enabled hop-by-hop headers removal on " + domain)
|
||||
} else {
|
||||
SystemWideLogger.Println("Disabled hop-by-hop headers removal on " + domain)
|
||||
}
|
||||
|
||||
utils.SendOK(w)
|
||||
|
||||
} else {
|
||||
http.Error(w, "405 - Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle view or edit HSTS states
|
||||
func HandleHSTSState(w http.ResponseWriter, r *http.Request) {
|
||||
domain, err := utils.PostPara(r, "domain")
|
||||
|
@ -4,9 +4,11 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/csrf"
|
||||
"imuslab.com/zoraxy/mod/sshprox"
|
||||
)
|
||||
|
||||
@ -42,11 +44,15 @@ func FSHandler(handler http.Handler) http.Handler {
|
||||
|
||||
// Allow access to /script/*, /img/pubic/* and /login.html without authentication
|
||||
if strings.HasPrefix(r.URL.Path, ppf("/script/")) || strings.HasPrefix(r.URL.Path, ppf("/img/public/")) || r.URL.Path == ppf("/login.html") || r.URL.Path == ppf("/reset.html") || r.URL.Path == ppf("/favicon.png") {
|
||||
if isHTMLFilePath(r.URL.Path) {
|
||||
handleInjectHTML(w, r, r.URL.Path)
|
||||
return
|
||||
}
|
||||
handler.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// check authentication
|
||||
// Check authentication
|
||||
if !authAgent.CheckAuth(r) && requireAuth {
|
||||
http.Redirect(w, r, ppf("/login.html"), http.StatusTemporaryRedirect)
|
||||
return
|
||||
@ -77,6 +83,10 @@ func FSHandler(handler http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
//Authenticated
|
||||
if isHTMLFilePath(r.URL.Path) {
|
||||
handleInjectHTML(w, r, r.URL.Path)
|
||||
return
|
||||
}
|
||||
handler.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@ -88,3 +98,53 @@ func ppf(relativeFilepath string) string {
|
||||
}
|
||||
return relativeFilepath
|
||||
}
|
||||
|
||||
func isHTMLFilePath(requestURI string) bool {
|
||||
return strings.HasSuffix(requestURI, ".html") || strings.HasSuffix(requestURI, "/")
|
||||
}
|
||||
|
||||
// Serve the html file with template token injected
|
||||
func handleInjectHTML(w http.ResponseWriter, r *http.Request, relativeFilepath string) {
|
||||
// Read the HTML file
|
||||
var content []byte
|
||||
var err error
|
||||
if len(relativeFilepath) > 0 && relativeFilepath[len(relativeFilepath)-1:] == "/" {
|
||||
relativeFilepath = relativeFilepath + "index.html"
|
||||
}
|
||||
if development {
|
||||
//Load from disk
|
||||
targetFilePath := strings.ReplaceAll(filepath.Join("web/", relativeFilepath), "\\", "/")
|
||||
content, err = os.ReadFile(targetFilePath)
|
||||
if err != nil {
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
//Load from embedded fs, require trimming off the prefix slash for relative path
|
||||
relativeFilepath = strings.TrimPrefix(relativeFilepath, "/")
|
||||
content, err = webres.ReadFile(relativeFilepath)
|
||||
if err != nil {
|
||||
SystemWideLogger.Println("load embedded web file failed: ", err)
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the file content to a string
|
||||
htmlContent := string(content)
|
||||
|
||||
//Defeine the system template for this request
|
||||
templateStrings := map[string]string{
|
||||
".csrfToken": csrf.Token(r),
|
||||
}
|
||||
|
||||
// Replace template tokens in the HTML content
|
||||
for key, value := range templateStrings {
|
||||
placeholder := "{{" + key + "}}"
|
||||
htmlContent = strings.ReplaceAll(htmlContent, placeholder, value)
|
||||
}
|
||||
|
||||
// Write the modified HTML content to the response
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
w.Write([]byte(htmlContent))
|
||||
}
|
||||
|
12
src/start.go
12
src/start.go
@ -84,7 +84,7 @@ func startupSequence() {
|
||||
})
|
||||
|
||||
//Create a TLS certificate manager
|
||||
tlsCertManager, err = tlscert.NewManager("./conf/certs", development)
|
||||
tlsCertManager, err = tlscert.NewManager("./conf/certs", development, SystemWideLogger)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -279,14 +279,20 @@ func startupSequence() {
|
||||
//Create a table just to store acme related preferences
|
||||
sysdb.NewTable("acmepref")
|
||||
acmeHandler = initACME()
|
||||
acmeAutoRenewer, err = acme.NewAutoRenewer("./conf/acme_conf.json", "./conf/certs/", int64(*acmeAutoRenewInterval), acmeHandler)
|
||||
acmeAutoRenewer, err = acme.NewAutoRenewer(
|
||||
"./conf/acme_conf.json",
|
||||
"./conf/certs/",
|
||||
int64(*acmeAutoRenewInterval),
|
||||
*acmeCertAutoRenewDays,
|
||||
acmeHandler,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
/* Docker UX Optimizer */
|
||||
if runtime.GOOS == "windows" && *runningInDocker {
|
||||
SystemWideLogger.PrintAndLog("WARNING", "Invalid start flag combination: docker=true && runtime.GOOS == windows. Running in docker UX development mode.", nil)
|
||||
SystemWideLogger.PrintAndLog("warning", "Invalid start flag combination: docker=true && runtime.GOOS == windows. Running in docker UX development mode.", nil)
|
||||
}
|
||||
DockerUXOptimizer = dockerux.NewDockerOptimizer(*runningInDocker, SystemWideLogger)
|
||||
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
|
||||
// List upstreams from a endpoint
|
||||
func ReverseProxyUpstreamList(w http.ResponseWriter, r *http.Request) {
|
||||
endpoint, err := utils.PostPara(r, "ep")
|
||||
endpoint, err := utils.GetPara(r, "ep")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "endpoint not defined")
|
||||
return
|
||||
|
@ -197,6 +197,8 @@ func ReverseProxyDeleteVdir(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
UpdateUptimeMonitorTargets()
|
||||
|
||||
utils.SendOK(w)
|
||||
}
|
||||
|
||||
|
@ -1000,7 +1000,7 @@
|
||||
*/
|
||||
function enableBlacklist() {
|
||||
var isChecked = $('#enableBlacklist').is(':checked');
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
type: 'POST',
|
||||
url: '/api/blacklist/enable',
|
||||
data: { enable: isChecked, id: currentEditingAccessRule},
|
||||
@ -1028,9 +1028,10 @@
|
||||
let counter = 0;
|
||||
for(var i = 0; i < ccs.length; i++){
|
||||
let thisCountryCode = ccs[i];
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
type: "POST",
|
||||
url: "/api/blacklist/country/add",
|
||||
method: "POST",
|
||||
data: { cc: thisCountryCode, id: currentEditingAccessRule},
|
||||
success: function(response) {
|
||||
if (response.error != undefined){
|
||||
@ -1066,7 +1067,7 @@
|
||||
function removeFromBannedList(countryCode){
|
||||
countryCode = countryCode.toLowerCase();
|
||||
let countryName = getCountryName(countryCode);
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/blacklist/country/remove",
|
||||
method: "POST",
|
||||
data: { cc: countryCode, id: currentEditingAccessRule},
|
||||
@ -1097,7 +1098,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/blacklist/ip/add",
|
||||
type: "POST",
|
||||
data: {ip: targetIp.toLowerCase(), id: currentEditingAccessRule},
|
||||
@ -1119,7 +1120,7 @@
|
||||
|
||||
function removeIpBlacklist(ipaddr){
|
||||
if (confirm("Confirm remove blacklist for " + ipaddr + " ?")){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/blacklist/ip/remove",
|
||||
type: "POST",
|
||||
data: {ip: ipaddr.toLowerCase(), id: currentEditingAccessRule},
|
||||
@ -1143,7 +1144,7 @@
|
||||
*/
|
||||
function enableWhitelist() {
|
||||
var isChecked = $('#enableWhitelist').is(':checked');
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
type: 'POST',
|
||||
url: '/api/whitelist/enable',
|
||||
data: { enable: isChecked , id: currentEditingAccessRule},
|
||||
@ -1165,7 +1166,7 @@
|
||||
let counter = 0;
|
||||
for(var i = 0; i < ccs.length; i++){
|
||||
let thisCountryCode = ccs[i];
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
type: "POST",
|
||||
url: "/api/whitelist/country/add",
|
||||
data: { cc: thisCountryCode , id: currentEditingAccessRule},
|
||||
@ -1199,7 +1200,7 @@
|
||||
function removeFromWhiteList(countryCode){
|
||||
if (confirm("Confirm removing " + getCountryName(countryCode) + " from whitelist?")){
|
||||
countryCode = countryCode.toLowerCase();
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/whitelist/country/remove",
|
||||
method: "POST",
|
||||
data: { cc: countryCode , id: currentEditingAccessRule},
|
||||
@ -1230,7 +1231,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/whitelist/ip/add",
|
||||
type: "POST",
|
||||
data: {ip: targetIp.toLowerCase(), "comment": remarks, id: currentEditingAccessRule},
|
||||
@ -1253,7 +1254,7 @@
|
||||
|
||||
function removeIpWhitelist(ipaddr){
|
||||
if (confirm("Confirm remove whitelist for " + ipaddr + " ?")){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/whitelist/ip/remove",
|
||||
type: "POST",
|
||||
data: {ip: ipaddr.toLowerCase(), id: currentEditingAccessRule},
|
||||
|
@ -161,6 +161,7 @@
|
||||
$(btn).addClass('disabled');
|
||||
$(btn).html(`<i class="ui loading spinner icon"></i>`);
|
||||
}
|
||||
|
||||
obtainCertificate(domain, dns, defaultCA.trim(), function(succ){
|
||||
if (btn != undefined){
|
||||
$(btn).removeClass('disabled');
|
||||
@ -256,7 +257,7 @@
|
||||
//Delete the certificate by its domain
|
||||
function deleteCertificate(domain){
|
||||
if (confirm("Confirm delete certificate for " + domain + " ?")){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/cert/delete",
|
||||
method: "POST",
|
||||
data: {domain: domain},
|
||||
@ -315,7 +316,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/acme/autoRenew/email",
|
||||
method: "POST",
|
||||
data: {"set": newDefaultEmail},
|
||||
@ -329,7 +330,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/acme/autoRenew/ca",
|
||||
data: {"set": newDefaultCA},
|
||||
method: "POST",
|
||||
@ -356,13 +357,16 @@
|
||||
});
|
||||
data.forEach(entry => {
|
||||
let isExpired = entry.RemainingDays <= 0;
|
||||
|
||||
let entryDomainRenewKey = entry.Domain;
|
||||
if (entryDomainRenewKey.includes("_.")){
|
||||
entryDomainRenewKey = entryDomainRenewKey.replace("_.","*.");
|
||||
}
|
||||
$("#certifiedDomainList").append(`<tr>
|
||||
<td><a style="cursor: pointer;" title="Download certificate" onclick="handleCertDownload('${entry.Domain}');">${entry.Domain}</a></td>
|
||||
<td>${entry.LastModifiedDate}</td>
|
||||
<td class="${isExpired?"expired":"valid"} certdate">${entry.ExpireDate} (${!isExpired?entry.RemainingDays+" days left":"Expired"})</td>
|
||||
<td><i class="${entry.UseDNS?"green check": "red times"} icon"></i></td>
|
||||
<td><button title="Renew Certificate" class="ui mini basic icon button renewButton" onclick="renewCertificate('${entry.Domain}', '${entry.UseDNS}', this);"><i class="ui green refresh icon"></i></button></td>
|
||||
<td><button title="Renew Certificate" class="ui mini basic icon button renewButton" onclick="renewCertificate('${entryDomainRenewKey}', '${entry.UseDNS}', this);"><i class="ui green refresh icon"></i></button></td>
|
||||
<td><button title="Delete key-pair" class="ui mini basic red icon button" onclick="deleteCertificate('${entry.Domain}');"><i class="ui red trash icon"></i></button></td>
|
||||
</tr>`);
|
||||
});
|
||||
@ -419,6 +423,8 @@
|
||||
}
|
||||
if (uploadPendingPublicKey && uploadPendingPrivateKey && typeof uploadPendingPublicKey === 'object' && typeof uploadPendingPrivateKey === 'object') {
|
||||
const publicKeyForm = new FormData();
|
||||
const csrfToken = document.querySelector('meta[name="zoraxy.csrf.Token"]').getAttribute("content");
|
||||
|
||||
publicKeyForm.append('file', uploadPendingPublicKey, 'publicKey');
|
||||
|
||||
const privateKeyForm = new FormData();
|
||||
@ -426,6 +432,7 @@
|
||||
|
||||
const publicKeyRequest = new XMLHttpRequest();
|
||||
publicKeyRequest.open('POST', '/api/cert/upload?ktype=pub&domain=' + domain);
|
||||
publicKeyRequest.setRequestHeader('X-CSRF-Token', csrfToken);
|
||||
publicKeyRequest.onreadystatechange = function() {
|
||||
if (publicKeyRequest.readyState === XMLHttpRequest.DONE) {
|
||||
if (publicKeyRequest.status !== 200) {
|
||||
@ -442,6 +449,7 @@
|
||||
|
||||
const privateKeyRequest = new XMLHttpRequest();
|
||||
privateKeyRequest.open('POST', '/api/cert/upload?ktype=pri&domain=' + domain);
|
||||
privateKeyRequest.setRequestHeader('X-CSRF-Token', csrfToken);
|
||||
privateKeyRequest.onreadystatechange = function() {
|
||||
if (privateKeyRequest.readyState === XMLHttpRequest.DONE) {
|
||||
if (privateKeyRequest.status !== 200) {
|
||||
@ -462,15 +470,11 @@
|
||||
//ktype = {"pub" / "pri"}
|
||||
function handleFileSelect(event, ktype="pub") {
|
||||
const file = event.target.files[0];
|
||||
//const fileNameInput = document.getElementById('selected-file-name');
|
||||
if (ktype == "pub"){
|
||||
uploadPendingPublicKey = file;
|
||||
}else if (ktype == "pri"){
|
||||
uploadPendingPrivateKey = file;
|
||||
}
|
||||
|
||||
|
||||
//fileNameInput.value = file.name;
|
||||
}
|
||||
|
||||
//Check if the default keypairs exists
|
||||
@ -493,14 +497,18 @@
|
||||
input.addEventListener('change', () => {
|
||||
// create form data object
|
||||
const formData = new FormData();
|
||||
|
||||
const csrfToken = document.querySelector('meta[name="zoraxy.csrf.Token"]').getAttribute("content");
|
||||
|
||||
// add selected file to form data
|
||||
formData.append('file', input.files[0]);
|
||||
|
||||
// send form data to server
|
||||
fetch('/api/cert/upload?ktype=pri', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
body: formData,
|
||||
headers: {
|
||||
'X-CSRF-Token': csrfToken
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
initDefaultKeypairCheck();
|
||||
@ -527,6 +535,7 @@
|
||||
function uploadPublicKey() {
|
||||
// create file input element
|
||||
const input = document.createElement('input');
|
||||
const csrfToken = document.querySelector('meta[name="zoraxy.csrf.Token"]').getAttribute("content");
|
||||
input.type = 'file';
|
||||
|
||||
// add change listener to file input
|
||||
@ -540,7 +549,10 @@
|
||||
// send form data to server
|
||||
fetch('/api/cert/upload?ktype=pub', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
body: formData,
|
||||
headers: {
|
||||
'X-CSRF-Token': csrfToken
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
|
@ -87,7 +87,7 @@
|
||||
}
|
||||
|
||||
function addGANet() {
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/gan/network/add",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
@ -191,7 +191,7 @@
|
||||
//Remove the given GANet
|
||||
function removeGANet(netid){
|
||||
if (confirm("Confirm remove Network " + netid + " PERMANENTLY ?"))
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/gan/network/remove",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
|
@ -214,7 +214,7 @@
|
||||
//Get CIDR from selected range group
|
||||
var cidr = $(".iprange.active").attr("cidr");
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/gan/network/setRange",
|
||||
metohd: "POST",
|
||||
data:{
|
||||
@ -240,7 +240,7 @@
|
||||
if (object != undefined){
|
||||
$(object).addClass("loading");
|
||||
}
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/gan/network/name",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -287,7 +287,7 @@
|
||||
|
||||
//Handle delete IP from memeber
|
||||
function deleteIpFromMemeber(memberid, ip){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/gan/members/ip",
|
||||
metohd: "POST",
|
||||
data: {
|
||||
@ -334,7 +334,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/gan/members/ip",
|
||||
metohd: "POST",
|
||||
data: {
|
||||
@ -461,7 +461,7 @@
|
||||
$(".memberName").each(function(){
|
||||
let addr = $(this).attr("addr");
|
||||
let targetDOM = $(this);
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/gan/members/name",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -487,7 +487,7 @@
|
||||
|
||||
let newname = prompt("Enter a easy manageable name for " + targetMemberAddr, "");
|
||||
if (newname != null && newname.trim() != "") {
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/gan/members/name",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -553,7 +553,7 @@
|
||||
function handleMemberAuth(object){
|
||||
let targetMemberAddr = $(object).attr("addr");
|
||||
let isAuthed = object.checked;
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/gan/members/authorize",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -580,7 +580,7 @@
|
||||
|
||||
function handleMemberDelete(addr){
|
||||
if (confirm("Confirm delete member " + addr + " ?")){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/gan/members/delete",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -605,7 +605,7 @@
|
||||
$(".addControllerToNetworkBtn").addClass("disabled");
|
||||
$(".addControllerToNetworkBtn").addClass("loading");
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/gan/network/join",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -630,7 +630,7 @@
|
||||
$(".removeControllerFromNetworkBtn").addClass("disabled");
|
||||
$(".removeControllerFromNetworkBtn").addClass("loading");
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/gan/network/leave",
|
||||
method: "POST",
|
||||
data: {
|
||||
|
@ -400,7 +400,7 @@
|
||||
let rateLimit = $(row).find(".RateLimit").val();
|
||||
let bypassGlobalTLS = $(row).find(".BypassGlobalTLS")[0].checked;
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/edit",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -422,6 +422,28 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//Generic functions for delete rp endpoints
|
||||
function deleteEndpoint(epoint){
|
||||
epoint = decodeURIComponent(epoint).hexDecode();
|
||||
if (confirm("Confirm remove proxy for :" + epoint + "?")){
|
||||
$.cjax({
|
||||
url: "/api/proxy/del",
|
||||
method: "POST",
|
||||
data: {ep: epoint},
|
||||
success: function(data){
|
||||
if (data.error == undefined){
|
||||
listProxyEndpoints();
|
||||
msgbox("Proxy Rule Deleted", true);
|
||||
reloadUptimeList();
|
||||
}else{
|
||||
msgbox(data.error, false);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* button events */
|
||||
function editBasicAuthCredentials(uuid){
|
||||
@ -474,7 +496,7 @@
|
||||
function handleProxyRuleToggle(object){
|
||||
let endpointUUID = $(object).attr("eptuuid");
|
||||
let isChecked = object.checked;
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/toggle",
|
||||
data: {
|
||||
"ep": endpointUUID,
|
||||
|
@ -339,7 +339,7 @@ function setWoLAddress() {
|
||||
$("#wol_mac").parent().removeClass("error");
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: wake_on_lan_API,
|
||||
type: "POST",
|
||||
data: {
|
||||
@ -363,7 +363,7 @@ function setWoLAddress() {
|
||||
|
||||
function delWoLAddr(mac, name) {
|
||||
if (confirm(`Confirm remove WoL record for ${name} (${mac}) ?`)){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: wake_on_lan_API,
|
||||
type: "POST",
|
||||
data: {
|
||||
@ -385,7 +385,7 @@ function wakeWoL(mac, object=undefined) {
|
||||
if (object != undefined){
|
||||
$(object).addClass("loading").addClass("disabled");
|
||||
}
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: wake_on_lan_API,
|
||||
type: "POST",
|
||||
data: {
|
||||
@ -594,7 +594,7 @@ function initForwardProxyInfo(){
|
||||
initForwardProxyInfo();
|
||||
|
||||
function toggleForwadProxy(enabled){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/tools/fwdproxy/enable",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -620,7 +620,7 @@ function updateForwardProxyPort(){
|
||||
$("#newPortNumber").parent().removeClass('error');
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/tools/fwdproxy/port",
|
||||
method: "POST",
|
||||
data: {
|
||||
|
@ -116,7 +116,7 @@
|
||||
let forwardChildpath = document.querySelector('input[name="forward-childpath"]').checked;
|
||||
let redirectType = document.querySelector('input[name="redirect-type"]:checked').value;
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/redirect/add",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -141,7 +141,7 @@
|
||||
let targetURL = $(obj).attr("rurl");
|
||||
targetURL = JSON.parse(decodeURIComponent(targetURL));
|
||||
if (confirm("Confirm remove redirection from " + targetURL + " ?")){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/redirect/delete",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -191,8 +191,9 @@
|
||||
|
||||
//Bind event to the checkbox
|
||||
$("#redirectRegex").on("change", function(){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/redirect/regex",
|
||||
method: "POST",
|
||||
data: {"enable": $(this)[0].checked},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
|
@ -181,8 +181,9 @@
|
||||
targetDomain = targetDomain.substring(8);
|
||||
$("#proxyRoot").val(targetDomain);
|
||||
}
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/tlscheck",
|
||||
method: "POST",
|
||||
data: {url: targetDomain},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
@ -232,7 +233,7 @@
|
||||
}
|
||||
|
||||
//Create the endpoint by calling add
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/add",
|
||||
data: {
|
||||
"type": "root",
|
||||
|
@ -212,8 +212,9 @@
|
||||
}
|
||||
|
||||
//Create the endpoint by calling add
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/add",
|
||||
method: "POST",
|
||||
data: {
|
||||
type: "host",
|
||||
rootname: rootname,
|
||||
@ -270,22 +271,6 @@
|
||||
|
||||
}
|
||||
|
||||
//Generic functions for delete rp endpoints
|
||||
function deleteEndpoint(epoint){
|
||||
epoint = decodeURIComponent(epoint).hexDecode();
|
||||
if (confirm("Confirm remove proxy for :" + epoint + "?")){
|
||||
$.ajax({
|
||||
url: "/api/proxy/del",
|
||||
data: {ep: epoint, },
|
||||
success: function(){
|
||||
listProxyEndpoints();
|
||||
msgbox("Proxy Rule Deleted", true);
|
||||
reloadUptimeList();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//Clearn the proxy target value, make sure user do not enter http:// or https://
|
||||
//and auto select TLS checkbox if https:// exists
|
||||
function autoFillTargetTLS(input){
|
||||
@ -307,12 +292,12 @@
|
||||
|
||||
//Automatic check if the site require TLS and check the checkbox if needed
|
||||
function autoCheckTls(targetDomain){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/tlscheck",
|
||||
data: {url: targetDomain},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
|
||||
msgbox(data.error, false);
|
||||
}else if (data == "https"){
|
||||
$("#reqTls").parent().checkbox("set checked");
|
||||
}else if (data == "http"){
|
||||
|
@ -315,26 +315,39 @@
|
||||
|
||||
//Start and stop service button
|
||||
function startService(){
|
||||
$.post("/api/proxy/enable", {enable: true}, function(data){
|
||||
if (data.error != undefined){
|
||||
msgbox(data.error, false, 5000);
|
||||
$.cjax({
|
||||
url: "/api/proxy/enable",
|
||||
method: "POST",
|
||||
data: {enable: true},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
msgbox(data.error, false, 5000);
|
||||
}
|
||||
initRPStaste();
|
||||
}
|
||||
initRPStaste();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function stopService(){
|
||||
$.post("/api/proxy/enable", {enable: false}, function(data){
|
||||
if (data.error != undefined){
|
||||
msgbox(data.error, false, 5000);
|
||||
$.cjax({
|
||||
url: "/api/proxy/enable",
|
||||
method: "POST",
|
||||
data: {enable: false},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
msgbox(data.error, false, 5000);
|
||||
}
|
||||
initRPStaste();
|
||||
}
|
||||
initRPStaste();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function handleP80ListenerStateChange(enabled){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/listenPort80",
|
||||
method: "POST",
|
||||
data: {"enable": enabled},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
@ -361,16 +374,21 @@
|
||||
return;
|
||||
}
|
||||
|
||||
$.post("/api/proxy/setIncoming", {incoming: newPortValue}, function(data){
|
||||
if (data.error != undefined){
|
||||
msgbox(data.error, false, 5000);
|
||||
return;
|
||||
}
|
||||
msgbox("Listening Port Updated");
|
||||
initRPStaste();
|
||||
$.cjax({
|
||||
url: "/api/proxy/setIncoming",
|
||||
method: "POST",
|
||||
data: {incoming: newPortValue},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
msgbox(data.error, false, 5000);
|
||||
return;
|
||||
}
|
||||
msgbox("Listening Port Updated");
|
||||
initRPStaste();
|
||||
|
||||
//Hide the reminder text
|
||||
$("#applyButtonReminder").hide();
|
||||
//Hide the reminder text
|
||||
$("#applyButtonReminder").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -402,8 +420,9 @@
|
||||
//Initiate the input listener on the checkbox
|
||||
$("#redirect").find("input").on("change", function(){
|
||||
let thisValue = $("#redirect").checkbox("is checked");
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/useHttpsRedirect",
|
||||
method: "POST",
|
||||
data: {set: thisValue},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
@ -440,9 +459,10 @@
|
||||
//Bind events to the checkbox
|
||||
$("#tlsMinVer").find("input").on("change", function(){
|
||||
let thisValue = $("#tlsMinVer").checkbox("is checked");
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/cert/tlsRequireLatest",
|
||||
data: {"set": thisValue},
|
||||
method: "POST",
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
msgbox(data.error, false, 5000);
|
||||
@ -498,15 +518,15 @@
|
||||
}else{
|
||||
$(".tlsEnabledOnly").addClass('disabled');
|
||||
}
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/cert/tls",
|
||||
method: "POST",
|
||||
data: {set: thisValue},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
alert(data.error);
|
||||
msgbox(data.error, false);
|
||||
}else{
|
||||
//Updated
|
||||
|
||||
//Check for case if the port is invalid default ports
|
||||
if ($("#incomingPort").val() == "80" && thisValue == true){
|
||||
confirmBox("Change listen port to :443?", function(choice){
|
||||
|
@ -100,7 +100,7 @@
|
||||
}
|
||||
|
||||
// Send the AJAX POST request
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
type: 'POST',
|
||||
url: '/api/streamprox/config/add',
|
||||
data: form.serialize(),
|
||||
@ -285,7 +285,7 @@
|
||||
}
|
||||
|
||||
// Send the AJAX POST request
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
type: 'POST',
|
||||
url: '/api/streamprox/config/edit',
|
||||
method: "POST",
|
||||
@ -316,7 +316,7 @@
|
||||
}
|
||||
|
||||
function deleteTCPProxyConfig(configUUID){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/streamprox/config/delete",
|
||||
method: "POST",
|
||||
data: {uuid: configUUID},
|
||||
@ -333,7 +333,7 @@
|
||||
|
||||
//Start a TCP proxy by their config UUID
|
||||
function startStreamProx(configUUID){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/streamprox/config/start",
|
||||
method: "POST",
|
||||
data: {uuid: configUUID},
|
||||
@ -351,7 +351,7 @@
|
||||
|
||||
//Stop a TCP proxy by their config UUID
|
||||
function stopStreamProx(configUUID){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/streamprox/config/stop",
|
||||
method: "POST",
|
||||
data: {uuid: configUUID},
|
||||
|
@ -233,7 +233,7 @@
|
||||
const newPassword = document.getElementsByName('newPassword')[0].value;
|
||||
const confirmNewPassword = document.getElementsByName('confirmNewPassword')[0].value;
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
type: "POST",
|
||||
url: "/api/auth/changePassword",
|
||||
data: {
|
||||
@ -279,7 +279,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
type: "POST",
|
||||
url: "/api/tools/smtp/set",
|
||||
data: data,
|
||||
|
@ -190,7 +190,7 @@
|
||||
function updateVDTargetTLSState(){
|
||||
var targetDomain = $("#virtualDirectoryDomain").val().trim();
|
||||
if (targetDomain != ""){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/tlscheck",
|
||||
data: {url: targetDomain},
|
||||
success: function(data){
|
||||
@ -252,7 +252,7 @@
|
||||
}
|
||||
|
||||
//Create a virtual directory endpoint
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/vdir/add",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -295,7 +295,7 @@
|
||||
epType = "root";
|
||||
path = "";
|
||||
}
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/vdir/del",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -384,7 +384,7 @@
|
||||
|
||||
//console.log(mathingPath, newDomain, requireTLS, skipValidation);
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/vdir/edit",
|
||||
method: "POST",
|
||||
data: {
|
||||
|
@ -164,7 +164,7 @@
|
||||
|
||||
$("#webserv_enableDirList").off("change").on("change", function(){
|
||||
let enable = $(this)[0].checked;
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/webserv/setDirList",
|
||||
method: "POST",
|
||||
data: {"enable": enable},
|
||||
@ -186,7 +186,7 @@
|
||||
confirmBox("This setting might cause port conflict. Continue Anyway?", function(choice){
|
||||
if (choice == true){
|
||||
//Continue anyway
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/webserv/setPort",
|
||||
method: "POST",
|
||||
data: {"port": newPort},
|
||||
@ -206,7 +206,7 @@
|
||||
}
|
||||
});
|
||||
}else{
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/webserv/setPort",
|
||||
method: "POST",
|
||||
data: {"port": newPort},
|
||||
|
@ -5,6 +5,7 @@
|
||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="theme-color" content="#4b75ff">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
<title>Control Panel | Zoraxy</title>
|
||||
<link rel="stylesheet" href="script/semantic/semantic.min.css">
|
||||
|
@ -4,6 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="robots" content="noindex" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
<title>Login | Zoraxy</title>
|
||||
<link rel="stylesheet" href="script/semantic/semantic.min.css">
|
||||
@ -250,10 +251,10 @@
|
||||
});
|
||||
|
||||
$("#regsiterbtn").on("click", function(event){
|
||||
var username = $("#username").val();
|
||||
var magic = $("#magic").val();
|
||||
var repeatMagic = $("#repeatMagic").val();
|
||||
|
||||
let username = $("#username").val();
|
||||
let magic = $("#magic").val();
|
||||
let repeatMagic = $("#repeatMagic").val();
|
||||
let csrfToken = document.getElementsByTagName("meta")["zoraxy.csrf.Token"].getAttribute("content");
|
||||
if (magic !== repeatMagic) {
|
||||
alert("Password does not match");
|
||||
return;
|
||||
@ -262,6 +263,9 @@
|
||||
$.ajax({
|
||||
url: "/api/auth/register",
|
||||
method: "POST",
|
||||
beforeSend: function(request) {
|
||||
request.setRequestHeader("X-CSRF-Token",csrfToken);
|
||||
},
|
||||
data: {
|
||||
username: username,
|
||||
password: magic
|
||||
@ -297,29 +301,45 @@
|
||||
|
||||
//Login system with the given username and password
|
||||
function login(){
|
||||
var username = $("#username").val();
|
||||
var magic = $("#magic").val();
|
||||
var rmbme = document.getElementById("rmbme").checked;
|
||||
let username = $("#username").val();
|
||||
let magic = $("#magic").val();
|
||||
let rmbme = document.getElementById("rmbme").checked;
|
||||
let csrfToken = document.getElementsByTagName("meta")["zoraxy.csrf.Token"].getAttribute("content");
|
||||
$("#errmsg").stop().finish().slideUp("fast");
|
||||
$("input").addClass('disabled');
|
||||
$.post(loginAddress, {"username": username, "password": magic, "rmbme": rmbme}).done(function(data){
|
||||
if (data.error !== undefined){
|
||||
//Something went wrong during the login
|
||||
$("#errmsg").html(`<i class="red remove icon"></i> ${data.error}`);
|
||||
$("#errmsg").stop().finish().slideDown('fast');
|
||||
}else if(data.redirect !== undefined){
|
||||
//LDAP Related Code
|
||||
window.location.href = data.redirect;
|
||||
}else{
|
||||
//Login succeed
|
||||
if (redirectionAddress == ""){
|
||||
//Redirect back to index
|
||||
window.location.href = "./";
|
||||
$.ajax({
|
||||
url: loginAddress,
|
||||
type: "POST",
|
||||
beforeSend: function(request) {
|
||||
request.setRequestHeader("X-CSRF-Token",csrfToken);
|
||||
},
|
||||
data: {
|
||||
"username": username,
|
||||
"password": magic,
|
||||
"rmbme": rmbme,
|
||||
},
|
||||
success: function(data){
|
||||
if (data.error !== undefined){
|
||||
//Something went wrong during the login
|
||||
$("#errmsg").html(`<i class="red remove icon"></i> ${data.error}`);
|
||||
$("#errmsg").stop().finish().slideDown('fast');
|
||||
}else if(data.redirect !== undefined){
|
||||
//LDAP Related Code
|
||||
window.location.href = data.redirect;
|
||||
}else{
|
||||
window.location.href = redirectionAddress;
|
||||
//Login succeed
|
||||
if (redirectionAddress == ""){
|
||||
//Redirect back to index
|
||||
window.location.href = "./";
|
||||
}else{
|
||||
window.location.href = redirectionAddress;
|
||||
}
|
||||
}
|
||||
$("input").removeClass('disabled');
|
||||
},
|
||||
error: function(){
|
||||
alert("Something went wrong.")
|
||||
}
|
||||
$("input").removeClass('disabled');
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<meta name="robots" content="noindex" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
@ -255,25 +256,36 @@
|
||||
}
|
||||
|
||||
// Send POST request with input values as data
|
||||
$.post('/api/account/new', { username: username, token: token, newpw: newPassword })
|
||||
.done(function(data) {
|
||||
// Handle successful response
|
||||
if (data.error != undefined){
|
||||
$("#errmsg").html(`<i class="red circle times icon"></i> ` + data.error);
|
||||
$("#errmsg").show();
|
||||
}else{
|
||||
$("#errmsg").hide();
|
||||
$("#countdown").hide();
|
||||
$("#succmsg").show();
|
||||
setTimeout(function(){
|
||||
window.location.href = "/";
|
||||
}, 3000);
|
||||
let csrfToken = document.getElementsByTagName("meta")["zoraxy.csrf.Token"].getAttribute("content");
|
||||
$.ajax({
|
||||
url: "/api/account/new",
|
||||
method: "POST",
|
||||
data: {
|
||||
username: username,
|
||||
token: token,
|
||||
newpw: newPassword
|
||||
},
|
||||
headers: {
|
||||
"X-CSRF-Token": csrfToken,
|
||||
},
|
||||
success: function(data){
|
||||
// Handle successful response
|
||||
if (data.error != undefined){
|
||||
$("#errmsg").html(`<i class="red circle times icon"></i> ` + data.error);
|
||||
$("#errmsg").show();
|
||||
}else{
|
||||
$("#errmsg").hide();
|
||||
$("#countdown").hide();
|
||||
$("#succmsg").show();
|
||||
setTimeout(function(){
|
||||
window.location.href = "/";
|
||||
}, 3000);
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
console.error(error);
|
||||
}
|
||||
})
|
||||
.fail(function(error) {
|
||||
// Handle error response
|
||||
console.error(error);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
@ -26,4 +26,18 @@ Object.defineProperty(String.prototype, 'capitalize', {
|
||||
return this.charAt(0).toUpperCase() + this.slice(1);
|
||||
},
|
||||
enumerable: false
|
||||
});
|
||||
});
|
||||
|
||||
//Add a new function to jquery for ajax override with csrf token injected
|
||||
$.cjax = function(payload){
|
||||
let requireTokenMethod = ["POST", "PUT", "DELETE"];;
|
||||
if (requireTokenMethod.includes(payload.method) || requireTokenMethod.includes(payload.type)){
|
||||
//csrf token is required
|
||||
let csrfToken = document.getElementsByTagName("meta")["zoraxy.csrf.Token"].getAttribute("content");
|
||||
payload.headers = {
|
||||
"X-CSRF-Token": csrfToken,
|
||||
}
|
||||
}
|
||||
|
||||
$.ajax(payload);
|
||||
}
|
@ -3,9 +3,11 @@
|
||||
<head>
|
||||
<!-- Notes: This should be open in its original path-->
|
||||
<meta charset="utf-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/utils.js"></script>
|
||||
<style>
|
||||
#refreshAccessRuleListBtn{
|
||||
position: absolute;
|
||||
@ -94,7 +96,7 @@
|
||||
$("#accessRuleForm input[name='accessRuleName']").val("");
|
||||
$("#accessRuleForm textarea[name='description']").val("");
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/access/create",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -162,7 +164,7 @@
|
||||
console.log('Access Rule Name:', accessRuleName);
|
||||
console.log('Description:', description);
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/access/update",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -238,7 +240,7 @@
|
||||
}
|
||||
let accessRuleName = $("#modifyRuleInfo input[name='accessRuleName']").val();
|
||||
if (confirm("Confirm removing access rule " + accessRuleName + "?")){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/access/remove",
|
||||
data: {
|
||||
"id": accessRuleUUID
|
||||
|
@ -3,9 +3,11 @@
|
||||
<head>
|
||||
<!-- Notes: This should be open in its original path-->
|
||||
<meta charset="utf-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/utils.js"></script>
|
||||
<style>
|
||||
.disabled.table{
|
||||
opacity: 0.5;
|
||||
@ -234,8 +236,9 @@
|
||||
initRenewerConfigFromFile();
|
||||
|
||||
function saveEmailToConfig(btn){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/acme/autoRenew/email",
|
||||
method: "POST",
|
||||
data: {set: $("#caRegisterEmail").val()},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
@ -256,27 +259,29 @@
|
||||
|
||||
function toggleAutoRenew(){
|
||||
var enabled = $("#enableCertAutoRenew").parent().checkbox("is checked");
|
||||
$.post("/api/acme/autoRenew/enable?enable=" + enabled, function(data){
|
||||
if (data.error){
|
||||
parent.msgbox(data.error, false, 5000);
|
||||
if (enabled){
|
||||
enableTrigerOnChangeEvent = false;
|
||||
$("#enableCertAutoRenew").parent().checkbox("set unchecked");
|
||||
enableTrigerOnChangeEvent = true;
|
||||
}
|
||||
if (parent && parent.setACMEEnableStates){
|
||||
parent.setACMEEnableStates(!enabled);
|
||||
}
|
||||
}else{
|
||||
$("#enableToggleSucc").stop().finish().fadeIn("fast").delay(3000).fadeOut("fast");
|
||||
if (parent && parent.setACMEEnableStates){
|
||||
parent.setACMEEnableStates(enabled);
|
||||
$.cjax({
|
||||
url: "/api/acme/autoRenew/enable",
|
||||
method: "POST",
|
||||
data: {"enable": enabled},
|
||||
success: function(data){
|
||||
if (data.error){
|
||||
parent.msgbox(data.error, false, 5000);
|
||||
if (enabled){
|
||||
enableTrigerOnChangeEvent = false;
|
||||
$("#enableCertAutoRenew").parent().checkbox("set unchecked");
|
||||
enableTrigerOnChangeEvent = true;
|
||||
}
|
||||
if (parent && parent.setACMEEnableStates){
|
||||
parent.setACMEEnableStates(!enabled);
|
||||
}
|
||||
}else{
|
||||
$("#enableToggleSucc").stop().finish().fadeIn("fast").delay(3000).fadeOut("fast");
|
||||
if (parent && parent.setACMEEnableStates){
|
||||
parent.setACMEEnableStates(enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//Render the domains table that exists in this zoraxy host
|
||||
@ -630,7 +635,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/acme/autoRenew/setDNS",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -843,8 +848,9 @@
|
||||
function saveAutoRenewPolicy(){
|
||||
let autoRenewAll = $("#renewAllSupported").parent().checkbox("is checked");
|
||||
if (autoRenewAll == true){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/acme/autoRenew/setDomains",
|
||||
method: "POST",
|
||||
data: {opr: "setAuto"},
|
||||
success: function(data){
|
||||
parent.msgbox("Renew policy rule updated")
|
||||
@ -856,8 +862,9 @@
|
||||
checkedNames.push($(this).attr('name'));
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/acme/autoRenew/setDomains",
|
||||
method: "POST",
|
||||
data: {opr: "setSelected", domains: JSON.stringify(checkedNames)},
|
||||
success: function(data){
|
||||
parent.msgbox("Renew policy rule updated")
|
||||
|
@ -3,9 +3,11 @@
|
||||
<head>
|
||||
<!-- Notes: This should be open in its original path-->
|
||||
<meta charset="utf-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<br>
|
||||
@ -46,7 +48,7 @@
|
||||
|
||||
function handleResetStats(){
|
||||
if (confirm("Confirm remove statistics from " + startDate + " to " + endDate +"?")){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/analytic/resetRange?start=" + startDate + "&end=" + endDate,
|
||||
method: "DELETE",
|
||||
success: function(data){
|
||||
|
@ -3,9 +3,11 @@
|
||||
<head>
|
||||
<!-- Notes: This should be open in its original path-->
|
||||
<meta charset="utf-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<br>
|
||||
@ -71,7 +73,7 @@
|
||||
}
|
||||
|
||||
function initAliasNames(){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/detail",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -130,7 +132,7 @@
|
||||
}
|
||||
|
||||
function saveCurrentAliasList(callback=undefined){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/setAlias",
|
||||
method: "POST",
|
||||
data:{
|
||||
|
@ -3,9 +3,11 @@
|
||||
<head>
|
||||
<!-- Notes: This should be open in its original path-->
|
||||
<meta charset="utf-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<br>
|
||||
@ -174,7 +176,7 @@
|
||||
parent.msgbox("Matching prefix cannot be empty!", false, 5000);
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/auth/exceptions/add",
|
||||
data:{
|
||||
ep: editingEndpoint.ep,
|
||||
@ -195,7 +197,7 @@
|
||||
|
||||
function removeExceptionPath(object){
|
||||
let matchingPrefix = $(object).attr("prefix");
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/auth/exceptions/delete",
|
||||
data:{
|
||||
ep: editingEndpoint.ep,
|
||||
@ -290,7 +292,7 @@
|
||||
}
|
||||
|
||||
function saveCredentials(){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/updateCredentials",
|
||||
method: "POST",
|
||||
data: {
|
||||
|
@ -3,9 +3,11 @@
|
||||
<head>
|
||||
<!-- Notes: This should be open in its original path-->
|
||||
<meta charset="utf-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<br>
|
||||
@ -70,10 +72,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("uploadForm").addEventListener("submit", function(event) {
|
||||
$("#uploadForm").submit(function(event) {
|
||||
event.preventDefault(); // Prevent the form from submitting normally
|
||||
|
||||
var fileInput = document.getElementById("fileInput");
|
||||
var fileInput = $("#fileInput")[0];
|
||||
var file = fileInput.files[0];
|
||||
if (!file) {
|
||||
alert("Missing file.");
|
||||
@ -83,18 +85,19 @@
|
||||
var formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "/api/conf/import", true);
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
if (xhr.status === 200) {
|
||||
parent.msgbox("Config restore succeed. Restart Zoraxy to apply changes.")
|
||||
} else {
|
||||
parent.msgbox("Restore failed: " + xhr.responseText, false, 5000);
|
||||
}
|
||||
$.cjax({
|
||||
url: "/api/conf/import",
|
||||
type: "POST",
|
||||
data: formData,
|
||||
processData: false, // Not to process the data
|
||||
contentType: false, // Not to set contentType
|
||||
success: function(response) {
|
||||
parent.msgbox("Config restore succeed. Restart Zoraxy to apply changes.");
|
||||
},
|
||||
error: function(xhr) {
|
||||
parent.msgbox("Restore failed: " + xhr.responseText, false, 5000);
|
||||
}
|
||||
};
|
||||
xhr.send(formData);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
@ -3,9 +3,11 @@
|
||||
<head>
|
||||
<!-- Notes: This should be open in its original path-->
|
||||
<meta charset="utf-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/utils.js"></script>
|
||||
<style>
|
||||
.ui.tabular.menu .item.narrowpadding{
|
||||
padding: 0.6em !important;
|
||||
@ -83,6 +85,40 @@
|
||||
<div class="ui divider"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui divider"></div>
|
||||
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
|
||||
<div class="ui fluid accordion">
|
||||
<div class="title">
|
||||
<i class="dropdown icon" tabindex="0"><div class="menu" tabindex="-1"></div></i>
|
||||
Advance Settings
|
||||
</div>
|
||||
<div class="content">
|
||||
<br>
|
||||
<div class="ui container">
|
||||
<h4>Overwrite Host Header</h4>
|
||||
<p>Manual override the automatic "Host" header rewrite logic. Leave empty for automatic.</p>
|
||||
<div class="ui fluid action input">
|
||||
<input type="text" id="manualHostOverwrite" placeholder="Overwrite Host name">
|
||||
<button onclick="updateManualHostOverwrite();" class="ui basic icon button" title="Update"><i class="ui green save icon"></i></button>
|
||||
<button onclick="clearManualHostOverwrite();" class="ui basic icon button" title="Clear"><i class="ui grey remove icon"></i></button>
|
||||
</div>
|
||||
|
||||
<div class="ui divider"></div>
|
||||
<h4>Remove Hop-by-hop Headers</h4>
|
||||
<p>Remove headers like "Connection" and "Keep-Alive" from both upstream and downstream requests. Set to ON by default.</p>
|
||||
<div class="ui toggle checkbox">
|
||||
<input type="checkbox" id="removeHopByHop" name="">
|
||||
<label>Remove Hop-by-hop Header<br>
|
||||
<small>This should be ON by default</small></label>
|
||||
</div>
|
||||
<div class="ui yellow message">
|
||||
<p><i class="exclamation triangle icon"></i>Settings in this section are for advanced users. Invalid settings might cause werid, unexpected behavior.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="ui tab basic segment" data-tab="security">
|
||||
<h4>HTTP Strict Transport Security</h4>
|
||||
@ -129,6 +165,7 @@
|
||||
|
||||
<script>
|
||||
$('.menu .item').tab();
|
||||
$(".accordion").accordion();
|
||||
let permissionPolicyKeys = [];
|
||||
|
||||
let editingEndpoint = {};
|
||||
@ -211,8 +248,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/header/add",
|
||||
method: "POST",
|
||||
data: {
|
||||
"type": getHeaderEditMode(),
|
||||
"domain": editingEndpoint.ep,
|
||||
@ -243,10 +281,10 @@
|
||||
}
|
||||
|
||||
function deleteCustomHeader(name){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/header/remove",
|
||||
method: "POST",
|
||||
data: {
|
||||
//"type": editingEndpoint.ept,
|
||||
"domain": editingEndpoint.ep,
|
||||
"name": name,
|
||||
},
|
||||
@ -263,6 +301,7 @@
|
||||
$("#headerTable").html(`<tr><td colspan="3"><i class="ui loading spinner icon"></i> Loading</td></tr>`);
|
||||
$.ajax({
|
||||
url: "/api/proxy/header/list",
|
||||
method: "GET",
|
||||
data: {
|
||||
"type": editingEndpoint.ept,
|
||||
"domain": editingEndpoint.ep,
|
||||
@ -271,7 +310,6 @@
|
||||
if (data.error != undefined){
|
||||
alert(data.error);
|
||||
}else{
|
||||
|
||||
$("#headerTable").html("");
|
||||
data.forEach(header => {
|
||||
let editModeIcon = header.IsRemove?`<i class="ui red times circle icon"></i>`:`<i class="ui green add circle icon"></i>`;
|
||||
@ -315,7 +353,7 @@
|
||||
/* Bind events to toggles */
|
||||
$("#enableHSTS").on("change", function(){
|
||||
let HSTSEnabled = $("#enableHSTS")[0].checked;
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/header/handleHSTS",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -390,7 +428,7 @@
|
||||
$("#permissionPolicyEditor").addClass("disabled");
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/header/handlePermissionPolicy",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -496,7 +534,7 @@
|
||||
let permissionPolicy = generatePermissionPolicyObject();
|
||||
let domain = editingEndpoint.ep;
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/header/handlePermissionPolicy",
|
||||
method: "PUT",
|
||||
data: {
|
||||
@ -512,6 +550,93 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/* Manual HOST header overwrite */
|
||||
function updateManualHostOverwrite(){
|
||||
updateManualHostOverwriteVal(function(data){
|
||||
if (data.error != undefined){
|
||||
parent.msgbox(data.error, false);
|
||||
}else{
|
||||
parent.msgbox("Host field Overwrite Updated");
|
||||
initManualHostOverwriteValue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function clearManualHostOverwrite(){
|
||||
$('#manualHostOverwrite').val('');
|
||||
updateManualHostOverwriteVal(function(data){
|
||||
if (data.error != undefined){
|
||||
parent.msgbox(data.error, false);
|
||||
}else{
|
||||
parent.msgbox("Host field Overwrite Cleared");
|
||||
initManualHostOverwriteValue();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function updateManualHostOverwriteVal(callback=undefined){
|
||||
let newHostname = $("#manualHostOverwrite").val().trim();
|
||||
$.cjax({
|
||||
url: "/api/proxy/header/handleHostOverwrite",
|
||||
method: "POST",
|
||||
data: {
|
||||
"domain": editingEndpoint.ep,
|
||||
"hostname": newHostname,
|
||||
},
|
||||
success: function(data){
|
||||
callback(data);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function initManualHostOverwriteValue(){
|
||||
$.get("/api/proxy/header/handleHostOverwrite?domain=" + editingEndpoint.ep, function(data){
|
||||
if (data.error != undefined){
|
||||
parent.msgbox(data.error, false);
|
||||
}else{
|
||||
$("#manualHostOverwrite").val(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
initManualHostOverwriteValue();
|
||||
|
||||
/* Hop-by-hop headers */
|
||||
function initHopByHopRemoverState(){
|
||||
$.get("/api/proxy/header/handleHopByHop?domain=" + editingEndpoint.ep, function(data){
|
||||
if (data.error != undefined){
|
||||
parent.msgbox(data.error);
|
||||
}else{
|
||||
if (data == true){
|
||||
$("#removeHopByHop").parent().checkbox("set checked");
|
||||
}else{
|
||||
$("#removeHopByHop").parent().checkbox("set unchecked");
|
||||
}
|
||||
|
||||
//Bind event to the checkbox
|
||||
$("#removeHopByHop").on("change", function(evt){
|
||||
let isChecked = $(this)[0].checked;
|
||||
$.cjax({
|
||||
url: "/api/proxy/header/handleHopByHop",
|
||||
method: "POST",
|
||||
data: {
|
||||
"domain": editingEndpoint.ep,
|
||||
"removeHopByHop": isChecked,
|
||||
},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
parent.msgbox(data.error, false);
|
||||
}else{
|
||||
parent.msgbox("Hop-by-Hop header rule updated");
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
initHopByHopRemoverState();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -3,9 +3,11 @@
|
||||
<head>
|
||||
<!-- Notes: This should be open in its original path-->
|
||||
<meta charset="utf-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/utils.js"></script>
|
||||
<style>
|
||||
.accessRule{
|
||||
cursor: pointer;
|
||||
@ -124,12 +126,10 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
initAccessRuleList(function(){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/detail",
|
||||
method: "POST",
|
||||
data: {"type":"host", "epname": editingEndpoint.ep },
|
||||
@ -160,7 +160,7 @@
|
||||
function applyChangeAndClose(){
|
||||
let newAccessRuleID = $(".accessRule.active").attr("ruleid");
|
||||
let targetEndpoint = editingEndpoint.ep;
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/access/attach",
|
||||
method: "POST",
|
||||
data: {
|
||||
|
@ -72,6 +72,18 @@
|
||||
<div class="ui divider"></div>
|
||||
<div id="logList" class="ui accordion">
|
||||
|
||||
</div>
|
||||
<div class="ui divider"></div>
|
||||
<h5>Filters</h5>
|
||||
<button style="margin-top: 0.4em;" filter="system" class="ui fluid basic small button filterbtn"><i class="ui blue info circle icon"></i> System</button>
|
||||
<button style="margin-top: 0.4em;" filter="request" class="ui fluid basic small button filterbtn"><i class="green exchange icon"></i> Request</button>
|
||||
<button style="margin-top: 0.4em;" filter="error" class="ui fluid basic small button filterbtn"><i class="red exclamation triangle icon"></i> Error</button>
|
||||
<button style="margin-top: 0.4em;" filter="all" class="ui fluid basic active small button filterbtn">All</button>
|
||||
<div class="ui divider"></div>
|
||||
<div class="ui toggle checkbox">
|
||||
<input type="checkbox" id="enableAutoScroll" onchange="handleAutoScrollTicker(event, this.checked);">
|
||||
<label>Auto Refresh<br>
|
||||
<small>Refresh the viewing log every 10 seconds</small></label>
|
||||
</div>
|
||||
<div class="ui divider"></div>
|
||||
<small>Notes: Some log files might be huge. Make sure you have checked the log file size before opening</small>
|
||||
@ -89,6 +101,10 @@
|
||||
</body>
|
||||
<script>
|
||||
var currentOpenedLogURL = "";
|
||||
var currentFilter = "all";
|
||||
var autoscroll = false;
|
||||
|
||||
$(".checkbox").checkbox();
|
||||
|
||||
function openLogInNewTab(){
|
||||
if (currentOpenedLogURL != ""){
|
||||
@ -105,7 +121,7 @@
|
||||
alert(data.error);
|
||||
return;
|
||||
}
|
||||
$("#logrender").val(data);
|
||||
renderLogWithCurrentFilter(data);
|
||||
});
|
||||
}
|
||||
|
||||
@ -151,5 +167,67 @@
|
||||
}
|
||||
return(n.toFixed(n < 10 && l > 0 ? 1 : 0) + ' ' + units[l]);
|
||||
}
|
||||
|
||||
//Filter the log and render it to text area based on current filter choice
|
||||
function renderLogWithCurrentFilter(data){
|
||||
if (currentFilter == "all"){
|
||||
$("#logrender").val(data);
|
||||
}else{
|
||||
let filterLines = data.split("\n");
|
||||
let filteredLogFile = "";
|
||||
for (var i = 0; i < filterLines.length; i++){
|
||||
const thisLine = filterLines[i];
|
||||
if (currentFilter == "system" && thisLine.indexOf("[system:") >= 0){
|
||||
filteredLogFile += thisLine + "\n";
|
||||
}else if (currentFilter == "request" && thisLine.indexOf("[router:") >= 0){
|
||||
filteredLogFile += thisLine + "\n";
|
||||
}else if (currentFilter == "error" && thisLine.indexOf(":error]") >= 0){
|
||||
filteredLogFile += thisLine + "\n";
|
||||
}
|
||||
}
|
||||
$("#logrender").val(filteredLogFile);
|
||||
}
|
||||
var textarea = document.getElementById('logrender');
|
||||
textarea.scrollTop = textarea.scrollHeight;
|
||||
}
|
||||
|
||||
/* Filter related functions */
|
||||
$(".filterbtn").on("click", function(evt){
|
||||
//Set filter type
|
||||
let filterType = $(this).attr("filter");
|
||||
currentFilter = (filterType);
|
||||
$(".filterbtn.active").removeClass("active");
|
||||
$(this).addClass('active');
|
||||
|
||||
//Reload the log with filter
|
||||
if (currentOpenedLogURL != ""){
|
||||
$.get(currentOpenedLogURL, function(data){
|
||||
if (data.error !== undefined){
|
||||
alert(data.error);
|
||||
return;
|
||||
}
|
||||
renderLogWithCurrentFilter(data);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/* Auto scroll function */
|
||||
setInterval(function(){
|
||||
if (autoscroll){
|
||||
//Update the log and scroll to bottom
|
||||
if (currentOpenedLogURL != ""){
|
||||
$.get(currentOpenedLogURL, function(data){
|
||||
if (data.error !== undefined){
|
||||
console.log(data.error);
|
||||
return;
|
||||
}
|
||||
renderLogWithCurrentFilter(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 10000);
|
||||
function handleAutoScrollTicker(event, checked){
|
||||
autoscroll = checked;
|
||||
}
|
||||
</script>
|
||||
</html>
|
@ -2,9 +2,11 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/utils.js"></script>
|
||||
<style>
|
||||
body{
|
||||
height: 100%;
|
||||
|
@ -3,9 +3,11 @@
|
||||
<head>
|
||||
<!-- Notes: This should be open in its original path-->
|
||||
<meta charset="utf-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/utils.js"></script>
|
||||
<style>
|
||||
.upstreamActions{
|
||||
position: absolute;
|
||||
@ -133,7 +135,7 @@
|
||||
function initOriginList(){
|
||||
$.ajax({
|
||||
url: "/api/proxy/upstream/list",
|
||||
method: "POST",
|
||||
method: "GET",
|
||||
data: {
|
||||
"type":"host",
|
||||
"ep": editingEndpoint.ep
|
||||
@ -284,8 +286,9 @@
|
||||
}else{
|
||||
//URL does not contains https or http protocol tag
|
||||
//sniff header
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/tlscheck",
|
||||
method: "POST",
|
||||
data: {url: targetDomain},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
@ -313,7 +316,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/upstream/add",
|
||||
method: "POST",
|
||||
data:{
|
||||
@ -365,7 +368,7 @@
|
||||
let newConfig = getUpstreamSettingFromDOM(targetDOM);
|
||||
let isActive = $(targetDOM).find(".enableState")[0].checked;
|
||||
console.log(newConfig);
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/upstream/update",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -418,8 +421,9 @@
|
||||
}else{
|
||||
//URL does not contains https or http protocol tag
|
||||
//sniff header
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/tlscheck",
|
||||
method: "POST",
|
||||
data: {url: targetDomain},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
@ -460,7 +464,7 @@
|
||||
|
||||
//Set a weight of a upstream
|
||||
function setUpstreamWeight(originIP, newWeight){
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/upstream/setPriority",
|
||||
method: "POST",
|
||||
data: {
|
||||
@ -489,7 +493,7 @@
|
||||
return;
|
||||
}
|
||||
//Remove the upstream
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/proxy/upstream/remove",
|
||||
method: "POST",
|
||||
data: {
|
||||
|
@ -2,12 +2,14 @@
|
||||
<head>
|
||||
<title>File Manager</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.6.0/jszip.min.js"></script>
|
||||
<link rel="stylesheet" href="fs.css">
|
||||
<script src="../script/utils.js"></script>
|
||||
<script>
|
||||
|
||||
</script>
|
||||
@ -199,7 +201,7 @@
|
||||
let counter = $(".fileObject.selected").length;
|
||||
$(".fileObject.selected").each(function(){
|
||||
let thisFilepath = $(this).attr("filepath");
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/fs/del?target=" + thisFilepath,
|
||||
method: "POST",
|
||||
success: function(data){
|
||||
@ -241,22 +243,9 @@
|
||||
let filename = $(this).attr("filename");
|
||||
if (ftype != "folder"){
|
||||
let ext = filepath.split(".").pop();
|
||||
if (isCodeFiles(ext)){
|
||||
editableCodeFiles.push({
|
||||
"filename": filename,
|
||||
"filepath": filepath
|
||||
});
|
||||
}else{
|
||||
openthis($(this), evt);
|
||||
}
|
||||
|
||||
openthis($(this), evt);
|
||||
}
|
||||
});
|
||||
|
||||
if (editableCodeFiles.length > 0){
|
||||
let hash = encodeURIComponent(JSON.stringify(editableCodeFiles))
|
||||
window.open("notepad/index.html#" + hash);
|
||||
}
|
||||
}
|
||||
|
||||
function refresh(){
|
||||
@ -571,12 +560,19 @@
|
||||
return;
|
||||
}
|
||||
|
||||
$.post("/api/fs/newFolder?path=" + currentPath + folderName, function(data){
|
||||
if (data.error != undefined){
|
||||
msgbox(data.error, false);
|
||||
}else{
|
||||
msgbox("Folder Created");
|
||||
refresh();
|
||||
$.cjax({
|
||||
url: "/api/fs/newFolder",
|
||||
method: "POST",
|
||||
data: {
|
||||
"path": currentPath + folderName,
|
||||
},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
msgbox(data.error, false);
|
||||
}else{
|
||||
msgbox("Folder Created");
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -597,8 +593,12 @@
|
||||
if (newName && newName != oldName) {
|
||||
// User entered a new name, perform renaming logic here
|
||||
console.log(oldPath, currentPath + newName);
|
||||
$.ajax({
|
||||
url: "/api/fs/move?srcpath=" + oldPath + "&destpath=" + currentPath + newName,
|
||||
$.cjax({
|
||||
url: "/api/fs/move",
|
||||
data: {
|
||||
"srcpath": oldPath,
|
||||
"destpath": currentPath + newName
|
||||
},
|
||||
method: "POST",
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
@ -826,6 +826,7 @@
|
||||
ajax.addEventListener("error", errorHandler, false);
|
||||
ajax.addEventListener("abort", abortHandler, false);
|
||||
ajax.open("POST", "/api/fs/upload?dir=" + dir);
|
||||
ajax.setRequestHeader("X-CSRF-Token", document.getElementsByTagName("meta")["zoraxy.csrf.Token"].getAttribute("content"));
|
||||
ajax.send(formdata);
|
||||
}
|
||||
|
||||
@ -914,8 +915,12 @@
|
||||
let filename = fileToPaste.filename;
|
||||
let filepath = fileToPaste.filepath;
|
||||
|
||||
$.ajax({
|
||||
url: "/api/fs/move?srcpath=" + filepath + "&destpath=" + currentPath + filename,
|
||||
$.cjax({
|
||||
url: "/api/fs/move",
|
||||
data:{
|
||||
"srcpath": filepath,
|
||||
"destpath": currentPath + filename,
|
||||
},
|
||||
method: "POST",
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
@ -939,7 +944,7 @@
|
||||
function copyFirstItemInQueueUntilAllCopied(){
|
||||
let file = copyPendingFiles.shift();
|
||||
let startingDir = currentPath;
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/fs/copy",
|
||||
method: "POST",
|
||||
data: {
|
||||
|
@ -1,6 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
|
||||
<meta charset="UTF-8">
|
||||
@ -13,6 +14,7 @@
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/tablesort.js"></script>
|
||||
<link rel="stylesheet" href="../main.css">
|
||||
<script src="../script/utils.js"></script>
|
||||
<style>
|
||||
.offlinehost{
|
||||
display: none;
|
||||
@ -86,9 +88,14 @@
|
||||
<div class="ui basic segment" align="center">
|
||||
<i class="loading spinner icon"></i> Scanning
|
||||
</div>`);
|
||||
$.post("/api/tools/ipscan", {start: start, end: end}, function(data) {
|
||||
displayResults(data);
|
||||
$(".scanbtn").removeClass("disabled");
|
||||
$.cjax({
|
||||
url: "/api/tools/ipscan",
|
||||
data: {start: start, end: end},
|
||||
method: "POST",
|
||||
success: function(data){
|
||||
displayResults(data);
|
||||
$(".scanbtn").removeClass("disabled");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -109,9 +116,14 @@
|
||||
<div class="ui basic segment" align="center">
|
||||
<i class="loading spinner icon"></i> Scanning
|
||||
</div>`);
|
||||
$.post("/api/tools/ipscan", {cidr: cidr}, function(data) {
|
||||
displayResults(data);
|
||||
$(".scanbtn").removeClass("disabled");
|
||||
$.cjax({
|
||||
url: "/api/tools/ipscan",
|
||||
method: "POST",
|
||||
data: {cidr: cidr},
|
||||
success: function(data) {
|
||||
displayResults(data);
|
||||
$(".scanbtn").removeClass("disabled");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
|
||||
<meta charset="UTF-8">
|
||||
@ -13,6 +14,7 @@
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/tablesort.js"></script>
|
||||
<link rel="stylesheet" href="../main.css">
|
||||
<script src="../script/utils.js"></script>
|
||||
<style>
|
||||
body{
|
||||
overflow-x: auto;
|
||||
@ -54,7 +56,7 @@
|
||||
var domain = $("#domain").val();
|
||||
$("#discover").addClass("loading").addClass('disabled');
|
||||
setCountdown();
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
type: "POST",
|
||||
url: "/api/mdns/discover",
|
||||
data: { domain: domain },
|
||||
|
@ -1,6 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
|
||||
<meta charset="UTF-8">
|
||||
@ -13,6 +14,7 @@
|
||||
<script src="../script/semantic/semantic.min.js"></script>
|
||||
<script src="../script/tablesort.js"></script>
|
||||
<link rel="stylesheet" href="../main.css">
|
||||
<script src="../script/utils.js"></script>
|
||||
<style>
|
||||
#loadingUI{
|
||||
width: 100%;
|
||||
@ -153,7 +155,7 @@
|
||||
//Try to ask the server side to create a ssh proxy object
|
||||
function createSSHProxy(remoteAddr, remotePort, username){
|
||||
//Request to create a ssh session instance
|
||||
$.ajax({
|
||||
$.cjax({
|
||||
url: "/api/tools/webssh",
|
||||
data: {ipaddr: remoteAddr, port: remotePort, username:username},
|
||||
method: "POST",
|
||||
|
@ -111,6 +111,7 @@ func HandleCountryDistrSummary(w http.ResponseWriter, r *http.Request) {
|
||||
func UpdateUptimeMonitorTargets() {
|
||||
if uptimeMonitor != nil {
|
||||
uptimeMonitor.Config.Targets = GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter)
|
||||
uptimeMonitor.CleanRecords()
|
||||
go func() {
|
||||
uptimeMonitor.ExecuteUptimeCheck()
|
||||
}()
|
||||
|
@ -79,27 +79,16 @@ func getExcludedDNSProviders() []string {
|
||||
"selectelv2", //Not sure why not working with our code generator
|
||||
"designate", //OpenStack, if you are using this you shd not be using zoraxy
|
||||
"mythicbeasts", //Module require url.URL, which cannot be automatically parsed
|
||||
"directadmin", //Reserve for next dependency update
|
||||
}
|
||||
}
|
||||
|
||||
// Exclude list for Windows build, due to limitations for lego versions
|
||||
func getExcludedDNSProvidersNT61() []string {
|
||||
return []string{
|
||||
"edgedns", //Too complex data structure
|
||||
"exec", //Not a DNS provider
|
||||
"httpreq", //Not a DNS provider
|
||||
"hurricane", //Multi-credentials arch
|
||||
"oraclecloud", //Evil company
|
||||
"acmedns", //Not a DNS provider
|
||||
"selectelv2", //Not sure why not working with our code generator
|
||||
"designate", //OpenStack, if you are using this you shd not be using zoraxy
|
||||
"mythicbeasts", //Module require url.URL, which cannot be automatically parsed
|
||||
|
||||
//The following suppliers was not in lego v1.15 (Windows 7 last supported version of lego)
|
||||
"cpanel",
|
||||
return append(getExcludedDNSProviders(), []string{"cpanel",
|
||||
"mailinabox",
|
||||
"shellrent",
|
||||
}
|
||||
}...)
|
||||
}
|
||||
|
||||
func isInSlice(str string, slice []string) bool {
|
||||
@ -227,6 +216,11 @@ func main() {
|
||||
case "*url.URL":
|
||||
fallthrough
|
||||
case "string":
|
||||
//Add exception rule for gandi baseURL
|
||||
if (providerName == "gandi" || providerName == "gandiv5") && fields[0] == "BaseURL" {
|
||||
//Not useful stuff. Ignore this field
|
||||
continue
|
||||
}
|
||||
configKeys = append(configKeys, &Field{
|
||||
Title: fields[0],
|
||||
Datatype: fields[1],
|
||||
@ -281,6 +275,7 @@ func main() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 5*time.Minute
|
||||
return ` + providerName + `.NewDNSProviderConfig(cfg)`
|
||||
|
||||
//Add fixed for Netcup timeout
|
||||
@ -292,7 +287,7 @@ func main() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.PropagationTimeout = 1200 * time.Second
|
||||
cfg.PropagationTimeout = 20*time.Minute
|
||||
return ` + providerName + `.NewDNSProviderConfig(cfg)`
|
||||
}
|
||||
generatedConvertcode += codeSegment
|
||||
|
33
tools/nt6.1_go_mod/NT_61_3.0.6.go.mod
Normal file
33
tools/nt6.1_go_mod/NT_61_3.0.6.go.mod
Normal file
@ -0,0 +1,33 @@
|
||||
module imuslab.com/zoraxy
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/boltdb/bolt v1.3.1
|
||||
github.com/go-acme/lego/v4 v4.15.0
|
||||
github.com/go-ping/ping v1.1.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/sessions v1.2.2
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/grandcat/zeroconf v1.0.0
|
||||
github.com/likexian/whois v1.15.2
|
||||
github.com/microcosm-cc/bluemonday v1.0.26
|
||||
golang.org/x/net v0.24.0
|
||||
golang.org/x/sys v0.19.0
|
||||
golang.org/x/text v0.14.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/gorilla/css v1.0.0 // indirect
|
||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||
github.com/miekg/dns v1.1.58 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
)
|
187
tools/nt6.1_go_mod/NT_61_3.0.7go.mod
Normal file
187
tools/nt6.1_go_mod/NT_61_3.0.7go.mod
Normal file
@ -0,0 +1,187 @@
|
||||
module imuslab.com/zoraxy
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/boltdb/bolt v1.3.1
|
||||
github.com/docker/docker v27.0.0+incompatible
|
||||
github.com/go-acme/lego/v4 v4.15.0
|
||||
github.com/go-ping/ping v1.1.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/sessions v1.2.2
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/grandcat/zeroconf v1.0.0
|
||||
github.com/likexian/whois v1.15.1
|
||||
github.com/microcosm-cc/bluemonday v1.0.26
|
||||
golang.org/x/net v0.25.0
|
||||
golang.org/x/sys v0.20.0
|
||||
golang.org/x/text v0.15.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute v1.25.1 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.1.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.1.0 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.22 // indirect
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.4.14 // indirect
|
||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 // indirect
|
||||
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.26.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.34.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.37.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect
|
||||
github.com/aws/smithy-go v1.19.0 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/civo/civogo v0.3.11 // indirect
|
||||
github.com/cloudflare/cloudflare-go v0.86.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/deepmap/oapi-codegen v1.9.1 // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/dnsimple/dnsimple-go v1.2.0 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/exoscale/egoscale v0.102.3 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/go-errors/errors v1.0.1 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-resty/resty/v2 v2.11.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.2 // indirect
|
||||
github.com/gophercloud/gophercloud v1.0.0 // indirect
|
||||
github.com/gorilla/css v1.0.1 // indirect
|
||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
|
||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
|
||||
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
|
||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
|
||||
github.com/labbsr0x/goh v1.0.1 // indirect
|
||||
github.com/linode/linodego v1.28.0 // indirect
|
||||
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
|
||||
github.com/liquidweb/liquidweb-go v1.6.4 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/miekg/dns v1.1.58 // indirect
|
||||
github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
|
||||
github.com/nrdcg/auroradns v1.1.0 // indirect
|
||||
github.com/nrdcg/bunny-go v0.0.0-20230728143221-c9dda82568d9 // indirect
|
||||
github.com/nrdcg/desec v0.7.0 // indirect
|
||||
github.com/nrdcg/dnspod-go v0.4.0 // indirect
|
||||
github.com/nrdcg/freemyip v0.2.0 // indirect
|
||||
github.com/nrdcg/goinwx v0.10.0 // indirect
|
||||
github.com/nrdcg/namesilo v0.2.1 // indirect
|
||||
github.com/nrdcg/nodion v0.1.0 // indirect
|
||||
github.com/nrdcg/porkbun v0.3.0 // indirect
|
||||
github.com/nzdjb/go-metaname v1.0.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/ovh/go-ovh v1.4.3 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/pquerna/otp v1.4.0 // indirect
|
||||
github.com/sacloud/api-client-go v0.2.8 // indirect
|
||||
github.com/sacloud/go-http v0.1.6 // indirect
|
||||
github.com/sacloud/iaas-api-go v1.11.1 // indirect
|
||||
github.com/sacloud/packages-go v0.0.9 // indirect
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.22 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
|
||||
github.com/softlayer/softlayer-go v1.1.3 // indirect
|
||||
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.9.0 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect
|
||||
github.com/transip/gotransip/v6 v6.23.0 // indirect
|
||||
github.com/ultradns/ultradns-go-sdk v1.6.1-20231103022937-8589b6a // indirect
|
||||
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
|
||||
github.com/vultr/govultr/v2 v2.17.2 // indirect
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f // indirect
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
go.uber.org/ratelimit v0.2.0 // indirect
|
||||
golang.org/x/crypto v0.23.0 // indirect
|
||||
golang.org/x/mod v0.16.0 // indirect
|
||||
golang.org/x/oauth2 v0.18.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.19.0 // indirect
|
||||
google.golang.org/api v0.169.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect
|
||||
google.golang.org/grpc v1.64.0 // indirect
|
||||
google.golang.org/protobuf v1.34.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/ns1/ns1-go.v2 v2.7.13 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gotest.tools/v3 v3.5.1 // indirect
|
||||
)
|
193
tools/nt6.1_go_mod/NT_61_3.1.0go.mod
Normal file
193
tools/nt6.1_go_mod/NT_61_3.1.0go.mod
Normal file
@ -0,0 +1,193 @@
|
||||
module imuslab.com/zoraxy
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/boltdb/bolt v1.3.1
|
||||
github.com/docker/docker v27.0.0+incompatible
|
||||
github.com/go-acme/lego/v4 v4.15.0
|
||||
github.com/go-ping/ping v1.1.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/csrf v1.7.0
|
||||
github.com/gorilla/sessions v1.2.2
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/grandcat/zeroconf v1.0.0
|
||||
github.com/likexian/whois v1.15.1
|
||||
github.com/microcosm-cc/bluemonday v1.0.26
|
||||
golang.org/x/net v0.25.0
|
||||
golang.org/x/sys v0.20.0
|
||||
golang.org/x/text v0.15.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute/metadata v0.3.0 // indirect
|
||||
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0-beta.4 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.22 // indirect
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.13 // indirect
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
|
||||
github.com/Microsoft/go-winio v0.4.14 // indirect
|
||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.62.712 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.27.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.38.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 // indirect
|
||||
github.com/aws/smithy-go v1.20.2 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/benbjohnson/clock v1.3.0 // indirect
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/civo/civogo v0.3.11 // indirect
|
||||
github.com/cloudflare/cloudflare-go v0.97.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/deepmap/oapi-codegen v1.9.1 // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/dnsimple/dnsimple-go v1.7.0 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/exoscale/egoscale v0.102.3 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/go-errors/errors v1.0.1 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-resty/resty/v2 v2.11.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.0.0 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
|
||||
github.com/gophercloud/gophercloud v1.12.0 // indirect
|
||||
github.com/gorilla/css v1.0.1 // indirect
|
||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
|
||||
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
|
||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
|
||||
github.com/labbsr0x/goh v1.0.1 // indirect
|
||||
github.com/linode/linodego v1.28.0 // indirect
|
||||
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
|
||||
github.com/liquidweb/liquidweb-go v1.6.4 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/miekg/dns v1.1.59 // indirect
|
||||
github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
|
||||
github.com/nrdcg/auroradns v1.1.0 // indirect
|
||||
github.com/nrdcg/bunny-go v0.0.0-20240207213615-dde5bf4577a3 // indirect
|
||||
github.com/nrdcg/desec v0.8.0 // indirect
|
||||
github.com/nrdcg/dnspod-go v0.4.0 // indirect
|
||||
github.com/nrdcg/freemyip v0.2.0 // indirect
|
||||
github.com/nrdcg/goinwx v0.10.0 // indirect
|
||||
github.com/nrdcg/mailinabox v0.2.0 // indirect
|
||||
github.com/nrdcg/namesilo v0.2.1 // indirect
|
||||
github.com/nrdcg/nodion v0.1.0 // indirect
|
||||
github.com/nrdcg/porkbun v0.3.0 // indirect
|
||||
github.com/nzdjb/go-metaname v1.0.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
||||
github.com/ovh/go-ovh v1.5.1 // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/pquerna/otp v1.4.0 // indirect
|
||||
github.com/sacloud/api-client-go v0.2.10 // indirect
|
||||
github.com/sacloud/go-http v0.1.8 // indirect
|
||||
github.com/sacloud/iaas-api-go v1.12.0 // indirect
|
||||
github.com/sacloud/packages-go v0.0.10 // indirect
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
|
||||
github.com/softlayer/softlayer-go v1.1.5 // indirect
|
||||
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.9.0 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.898 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.898 // indirect
|
||||
github.com/transip/gotransip/v6 v6.23.0 // indirect
|
||||
github.com/ultradns/ultradns-go-sdk v1.6.1-20231103022937-8589b6a // indirect
|
||||
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
|
||||
github.com/vultr/govultr/v2 v2.17.2 // indirect
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20240318083951-4fe6125f286e // indirect
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20240318084659-dfa50323a0b4 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
go.uber.org/ratelimit v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.23.0 // indirect
|
||||
golang.org/x/mod v0.18.0 // indirect
|
||||
golang.org/x/oauth2 v0.21.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
google.golang.org/api v0.172.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect
|
||||
google.golang.org/grpc v1.64.0 // indirect
|
||||
google.golang.org/protobuf v1.34.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/ns1/ns1-go.v2 v2.7.13 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gotest.tools/v3 v3.5.1 // indirect
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user