Skip to content

Commit

Permalink
System arch optimization
Browse files Browse the repository at this point in the history
- Optimized types and definitions
- Moved shutdown seq to start.go file
- Moved authelia to auth/sso module
- Added different auth types support (wip)
- Updated proxy config structure
- Added v3.1.4 to v3.1.5 auto upgrade utilities
- Fixed #426
- Optimized status page UI
- Added options to disable uptime montior in config
  • Loading branch information
tobychui committed Dec 12, 2024
1 parent 9e95d84 commit bb0f550
Show file tree
Hide file tree
Showing 23 changed files with 689 additions and 215 deletions.
28 changes: 16 additions & 12 deletions src/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func LoadReverseProxyConfig(configFilepath string) error {
thisConfigEndpoint.RootOrMatchingDomain = "/"
}

if thisConfigEndpoint.ProxyType == dynamicproxy.ProxyType_Root {
if thisConfigEndpoint.ProxyType == dynamicproxy.ProxyTypeRoot {
//This is a root config file
rootProxyEndpoint, err := dynamicProxyRouter.PrepareProxyRoute(&thisConfigEndpoint)
if err != nil {
Expand All @@ -68,7 +68,7 @@ func LoadReverseProxyConfig(configFilepath string) error {

dynamicProxyRouter.SetProxyRouteAsRoot(rootProxyEndpoint)

} else if thisConfigEndpoint.ProxyType == dynamicproxy.ProxyType_Host {
} else if thisConfigEndpoint.ProxyType == dynamicproxy.ProxyTypeHost {
//This is a host config file
readyProxyEndpoint, err := dynamicProxyRouter.PrepareProxyRoute(&thisConfigEndpoint)
if err != nil {
Expand Down Expand Up @@ -97,7 +97,7 @@ func filterProxyConfigFilename(filename string) string {
func SaveReverseProxyConfig(endpoint *dynamicproxy.ProxyEndpoint) error {
//Get filename for saving
filename := filepath.Join("./conf/proxy/", endpoint.RootOrMatchingDomain+".config")
if endpoint.ProxyType == dynamicproxy.ProxyType_Root {
if endpoint.ProxyType == dynamicproxy.ProxyTypeRoot {
filename = "./conf/proxy/root.config"
}

Expand Down Expand Up @@ -129,9 +129,15 @@ func RemoveReverseProxyConfig(endpoint string) error {
// Get the default root config that point to the internal static web server
// this will be used if root config is not found (new deployment / missing root.config file)
func GetDefaultRootConfig() (*dynamicproxy.ProxyEndpoint, error) {
//Default Authentication Provider
defaultAuth := &dynamicproxy.AuthenticationProvider{
AuthMethod: dynamicproxy.AuthMethodNone,
BasicAuthCredentials: []*dynamicproxy.BasicAuthCredentials{},
BasicAuthExceptionRules: []*dynamicproxy.BasicAuthExceptionRule{},
}
//Default settings
rootProxyEndpoint, err := dynamicProxyRouter.PrepareProxyRoute(&dynamicproxy.ProxyEndpoint{
ProxyType: dynamicproxy.ProxyType_Root,
ProxyType: dynamicproxy.ProxyTypeRoot,
RootOrMatchingDomain: "/",
ActiveOrigins: []*loadbalance.Upstream{
{
Expand All @@ -141,14 +147,12 @@ func GetDefaultRootConfig() (*dynamicproxy.ProxyEndpoint, error) {
Weight: 0,
},
},
InactiveOrigins: []*loadbalance.Upstream{},
BypassGlobalTLS: false,
VirtualDirectories: []*dynamicproxy.VirtualDirectoryEndpoint{},
RequireBasicAuth: false,
BasicAuthCredentials: []*dynamicproxy.BasicAuthCredentials{},
BasicAuthExceptionRules: []*dynamicproxy.BasicAuthExceptionRule{},
DefaultSiteOption: dynamicproxy.DefaultSite_InternalStaticWebServer,
DefaultSiteValue: "",
InactiveOrigins: []*loadbalance.Upstream{},
BypassGlobalTLS: false,
VirtualDirectories: []*dynamicproxy.VirtualDirectoryEndpoint{},
AuthenticationProvider: defaultAuth,
DefaultSiteOption: dynamicproxy.DefaultSite_InternalStaticWebServer,
DefaultSiteValue: "",
})
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion src/def.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const (
/* Build Constants */
SYSTEM_NAME = "Zoraxy"
SYSTEM_VERSION = "3.1.5"
DEVELOPMENT_BUILD = true /* Development: Set to false to use embedded web fs */
DEVELOPMENT_BUILD = false /* Development: Set to false to use embedded web fs */

/* System Constants */
DATABASE_PATH = "sys.db"
Expand Down
43 changes: 1 addition & 42 deletions src/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,47 +57,6 @@ func SetupCloseHandler() {
}()
}

func ShutdownSeq() {
SystemWideLogger.Println("Shutting down " + SYSTEM_NAME)
SystemWideLogger.Println("Closing Netstats Listener")
if netstatBuffers != nil {
netstatBuffers.Close()
}

SystemWideLogger.Println("Closing Statistic Collector")
if statisticCollector != nil {
statisticCollector.Close()
}

if mdnsTickerStop != nil {
SystemWideLogger.Println("Stopping mDNS Discoverer (might take a few minutes)")
// Stop the mdns service
mdnsTickerStop <- true
}
if mdnsScanner != nil {
mdnsScanner.Close()
}
SystemWideLogger.Println("Shutting down load balancer")
if loadBalancer != nil {
loadBalancer.Close()
}
SystemWideLogger.Println("Closing Certificates Auto Renewer")
if acmeAutoRenewer != nil {
acmeAutoRenewer.Close()
}
//Remove the tmp folder
SystemWideLogger.Println("Cleaning up tmp files")
os.RemoveAll("./tmp")

//Close database
SystemWideLogger.Println("Stopping system database")
sysdb.Close()

//Close logger
SystemWideLogger.Println("Closing system wide logger")
SystemWideLogger.Close()
}

func main() {
//Parse startup flags
flag.Parse()
Expand Down Expand Up @@ -141,7 +100,7 @@ func main() {
csrf.SameSite(csrf.SameSiteLaxMode),
)

//Startup all modules
//Startup all modules, see start.go
startupSequence()

//Initiate management interface APIs
Expand Down
87 changes: 87 additions & 0 deletions src/mod/auth/sso/authelia/authelia.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package authelia

import (
"errors"
"fmt"
"net/http"
"net/url"

"imuslab.com/zoraxy/mod/dynamicproxy"
"imuslab.com/zoraxy/mod/info/logger"
)

type Options struct {
AutheliaURL string //URL of the Authelia server, e.g. authelia.example.com
UseHTTPS bool //Whether to use HTTPS for the Authelia server
Logger logger.Logger
}

type AutheliaHandler struct {
options *Options
}

func NewAutheliaAuthenticator(options *Options) *AutheliaHandler {
return &AutheliaHandler{
options: options,
}
}

// HandleAutheliaAuthRouting is the handler for Authelia authentication, if the error is not nil, the request will be forwarded to the endpoint
// Do not continue processing or write to the response writer if the error is not nil
func (h *AutheliaHandler) HandleAutheliaAuthRouting(w http.ResponseWriter, r *http.Request, pe *dynamicproxy.ProxyEndpoint) error {
err := h.handleAutheliaAuth(w, r)
if err != nil {
return nil
}
return err
}

func (h *AutheliaHandler) handleAutheliaAuth(w http.ResponseWriter, r *http.Request) error {
client := &http.Client{}

protocol := "http"
if h.options.UseHTTPS {
protocol = "https"
}

autheliaBaseURL := protocol + "://" + h.options.AutheliaURL
//Remove tailing slash if any
if autheliaBaseURL[len(autheliaBaseURL)-1] == '/' {
autheliaBaseURL = autheliaBaseURL[:len(autheliaBaseURL)-1]
}

//Make a request to Authelia to verify the request
req, err := http.NewRequest("POST", autheliaBaseURL+"/api/verify", nil)
if err != nil {
h.options.Logger.PrintAndLog("Authelia", "Unable to create request", err)
w.WriteHeader(401)
return errors.New("unauthorized")
}

scheme := "http"
if r.TLS != nil {
scheme = "https"
}
req.Header.Add("X-Original-URL", fmt.Sprintf("%s://%s", scheme, r.Host))

// Copy cookies from the incoming request
for _, cookie := range r.Cookies() {
req.AddCookie(cookie)
}

// Making the verification request
resp, err := client.Do(req)
if err != nil {
h.options.Logger.PrintAndLog("Authelia", "Unable to verify", err)
w.WriteHeader(401)
return errors.New("unauthorized")
}

if resp.StatusCode != 200 {
redirectURL := autheliaBaseURL + "/?rd=" + url.QueryEscape(scheme+"://"+r.Host+r.URL.String()) + "&rm=" + r.Method
http.Redirect(w, r, redirectURL, http.StatusSeeOther)
return errors.New("unauthorized")
}

return nil
}
4 changes: 2 additions & 2 deletions src/mod/database/dbleveldb/dbleveldb.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ func NewDB(path string) (*DB, error) {
batch: leveldb.Batch{},
}

//Create a ticker to flush data into disk every 5 seconds
writeFlushTicker := time.NewTicker(5 * time.Second)
//Create a ticker to flush data into disk every 1 seconds
writeFlushTicker := time.NewTicker(1 * time.Second)
writeFlushStop := make(chan bool)
go func() {
for {
Expand Down
20 changes: 11 additions & 9 deletions src/mod/dynamicproxy/Server.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,18 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}

//SSO Interception Mode
if sep.UseSSOIntercept {
allowPass := h.Parent.Option.SSOHandler.ServeForwardAuth(w, r)
if !allowPass {
h.Parent.Option.Logger.LogHTTPRequest(r, "sso-x", 307)
return
/*
if sep.AuthenticationProvider.SSOInterceptMode {
allowPass := h.Parent.Option.SSOHandler.ServeForwardAuth(w, r)
if !allowPass {
h.Parent.Option.Logger.LogHTTPRequest(r, "sso-x", 307)
return
}
}
}
*/

//Validate basic auth
if sep.RequireBasicAuth {
if sep.AuthenticationProvider.AuthMethod == AuthMethodBasic {
err := h.handleBasicAuthRouting(w, r, sep)
if err != nil {
h.Parent.Option.Logger.LogHTTPRequest(r, "host", 401)
Expand All @@ -108,7 +110,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
//Virtual directory routing rule found. Route via vdir mode
h.vdirRequest(w, r, targetProxyEndpoint)
return
} else if !strings.HasSuffix(proxyingPath, "/") && sep.ProxyType != ProxyType_Root {
} else if !strings.HasSuffix(proxyingPath, "/") && sep.ProxyType != ProxyTypeRoot {
potentialProxtEndpoint := sep.GetVirtualDirectoryHandlerFromRequestURI(proxyingPath + "/")
if potentialProxtEndpoint != nil && !potentialProxtEndpoint.Disabled {
//Missing tailing slash. Redirect to target proxy endpoint
Expand Down Expand Up @@ -180,7 +182,7 @@ func (h *ProxyHandler) handleRootRouting(w http.ResponseWriter, r *http.Request)
//Virtual directory routing rule found. Route via vdir mode
h.vdirRequest(w, r, targetProxyEndpoint)
return
} else if !strings.HasSuffix(proxyingPath, "/") && proot.ProxyType != ProxyType_Root {
} else if !strings.HasSuffix(proxyingPath, "/") && proot.ProxyType != ProxyTypeRoot {
potentialProxtEndpoint := proot.GetVirtualDirectoryHandlerFromRequestURI(proxyingPath + "/")
if potentialProxtEndpoint != nil && !targetProxyEndpoint.Disabled {
//Missing tailing slash. Redirect to target proxy endpoint
Expand Down
57 changes: 0 additions & 57 deletions src/mod/dynamicproxy/authelia.go

This file was deleted.

6 changes: 3 additions & 3 deletions src/mod/dynamicproxy/basicAuth.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ func (h *ProxyHandler) handleBasicAuthRouting(w http.ResponseWriter, r *http.Req
// Handle basic auth logic
// do not write to http.ResponseWriter if err return is not nil (already handled by this function)
func handleBasicAuth(w http.ResponseWriter, r *http.Request, pe *ProxyEndpoint) error {
if len(pe.BasicAuthExceptionRules) > 0 {
if len(pe.AuthenticationProvider.BasicAuthExceptionRules) > 0 {
//Check if the current path matches the exception rules
for _, exceptionRule := range pe.BasicAuthExceptionRules {
for _, exceptionRule := range pe.AuthenticationProvider.BasicAuthExceptionRules {
if strings.HasPrefix(r.RequestURI, exceptionRule.PathPrefix) {
//This path is excluded from basic auth
return nil
Expand All @@ -46,7 +46,7 @@ func handleBasicAuth(w http.ResponseWriter, r *http.Request, pe *ProxyEndpoint)
//Check for the credentials to see if there is one matching
hashedPassword := auth.Hash(p)
matchingFound := false
for _, cred := range pe.BasicAuthCredentials {
for _, cred := range pe.AuthenticationProvider.BasicAuthCredentials {
if u == cred.Username && hashedPassword == cred.PasswordHash {
matchingFound = true

Expand Down
6 changes: 3 additions & 3 deletions src/mod/dynamicproxy/dynamicproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func (router *Router) StartProxyService() error {
}

//Validate basic auth
if sep.RequireBasicAuth {
if sep.AuthenticationProvider.AuthMethod == AuthMethodBasic {
err := handleBasicAuth(w, r, sep)
if err != nil {
return
Expand All @@ -161,8 +161,8 @@ func (router *Router) StartProxyService() error {
ProxyDomain: selectedUpstream.OriginIpOrDomain,
OriginalHost: originalHostHeader,
UseTLS: selectedUpstream.RequireTLS,
HostHeaderOverwrite: sep.RequestHostOverwrite,
NoRemoveHopByHop: sep.DisableHopByHopHeaderRemoval,
HostHeaderOverwrite: sep.HeaderRewriteRules.RequestHostOverwrite,
NoRemoveHopByHop: sep.HeaderRewriteRules.DisableHopByHopHeaderRemoval,
PathPrefix: "",
Version: sep.parent.Option.HostVersion,
})
Expand Down
Loading

0 comments on commit bb0f550

Please sign in to comment.