diff --git a/src/acme.go b/src/acme.go index f1b54c5..4dd7cd4 100644 --- a/src/acme.go +++ b/src/acme.go @@ -101,6 +101,7 @@ func AcmeCheckAndHandleRenewCertificate(w http.ResponseWriter, r *http.Request) } else { //This port do not support ACME utils.SendErrorResponse(w, "ACME renew only support web server listening on port 80 (http) or 443 (https)") + return } //Add a 3 second delay to make sure everything is settle down @@ -109,6 +110,10 @@ func AcmeCheckAndHandleRenewCertificate(w http.ResponseWriter, r *http.Request) // Pass over to the acmeHandler to deal with the communication acmeHandler.HandleRenewCertificate(w, r) + //Update the TLS cert store buffer + tlsCertManager.UpdateLoadedCertList() + + //Restore original settings if dynamicProxyRouter.Option.Port == 443 { if !isForceHttpsRedirectEnabledOriginally { //Default is off. Turn the redirection off diff --git a/src/emails.go b/src/emails.go index 55fd604..529d25d 100644 --- a/src/emails.go +++ b/src/emails.go @@ -25,12 +25,6 @@ func HandleSMTPSet(w http.ResponseWriter, r *http.Request) { return } - domain, err := utils.PostPara(r, "domain") - if err != nil { - utils.SendErrorResponse(w, "domain cannot be empty") - return - } - portString, err := utils.PostPara(r, "port") if err != nil { utils.SendErrorResponse(w, "port must be a valid integer") @@ -76,7 +70,6 @@ func HandleSMTPSet(w http.ResponseWriter, r *http.Request) { //Set the email sender properties thisEmailSender := email.Sender{ Hostname: strings.TrimSpace(hostname), - Domain: strings.TrimSpace(domain), Port: port, Username: strings.TrimSpace(username), Password: strings.TrimSpace(password), @@ -206,7 +199,7 @@ var ( ) func HandleAdminAccountResetEmail(w http.ResponseWriter, r *http.Request) { - if EmailSender.Username == "" || EmailSender.Domain == "" { + if EmailSender.Username == "" { //Reset account not setup utils.SendErrorResponse(w, "Reset account not setup.") return diff --git a/src/main.go b/src/main.go index 25cafd7..52aee68 100644 --- a/src/main.go +++ b/src/main.go @@ -41,6 +41,7 @@ var noauth = flag.Bool("noauth", false, "Disable authentication for management i var showver = flag.Bool("version", false, "Show version of this server") var allowSshLoopback = flag.Bool("sshlb", false, "Allow loopback web ssh connection (DANGER)") var allowMdnsScanning = flag.Bool("mdns", true, "Enable mDNS scanner and transponder") +var mdnsName = flag.String("mdnsname", "", "mDNS name, leave empty to use default (zoraxy_{node-uuid}.local)") var ztAuthToken = flag.String("ztauth", "", "ZeroTier authtoken for the local node") var ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port") var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)") @@ -51,7 +52,7 @@ var logOutputToFile = flag.Bool("log", true, "Log terminal output to file") var ( name = "Zoraxy" - version = "3.0.2" + version = "3.0.3" nodeUUID = "generic" development = false //Set this to false to use embedded web fs bootTime = time.Now().Unix() diff --git a/src/mod/access/access.go b/src/mod/access/access.go index c105c63..ae5cd9b 100644 --- a/src/mod/access/access.go +++ b/src/mod/access/access.go @@ -69,6 +69,9 @@ func NewAccessController(options *Options) (*Controller, error) { Options: options, } + //Assign default access rule parent + thisController.DefaultAccessRule.parent = &thisController + //Load all acccess rules from file configFiles, err := filepath.Glob(options.ConfigFolder + "/*.json") if err != nil { @@ -113,6 +116,7 @@ func (c *Controller) GetGlobalAccessRule() (*AccessRule, error) { // Load access rules to runtime, require rule ID func (c *Controller) GetAccessRuleByID(accessRuleID string) (*AccessRule, error) { if accessRuleID == "default" || accessRuleID == "" { + return c.DefaultAccessRule, nil } //Load from sync.Map, should be O(1) diff --git a/src/mod/access/blacklist.go b/src/mod/access/blacklist.go index ec243ae..7daab35 100644 --- a/src/mod/access/blacklist.go +++ b/src/mod/access/blacklist.go @@ -2,6 +2,8 @@ package access import ( "strings" + + "imuslab.com/zoraxy/mod/netutils" ) /* @@ -71,5 +73,22 @@ func (s *AccessRule) GetAllBlacklistedIp() []string { func (s *AccessRule) IsIPBlacklisted(ipAddr string) bool { IPBlacklist := *s.BlackListIP _, ok := IPBlacklist[ipAddr] - return ok + if ok { + return true + } + + //Check for CIDR + for ipOrCIDR, _ := range IPBlacklist { + wildcardMatch := netutils.MatchIpWildcard(ipAddr, ipOrCIDR) + if wildcardMatch { + return true + } + + cidrMatch := netutils.MatchIpCIDR(ipAddr, ipOrCIDR) + if cidrMatch { + return true + } + } + + return false } diff --git a/src/mod/dynamicproxy/Server.go b/src/mod/dynamicproxy/Server.go index eb1314f..129192b 100644 --- a/src/mod/dynamicproxy/Server.go +++ b/src/mod/dynamicproxy/Server.go @@ -87,7 +87,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } else if !strings.HasSuffix(proxyingPath, "/") && sep.ProxyType != ProxyType_Root { potentialProxtEndpoint := sep.GetVirtualDirectoryHandlerFromRequestURI(proxyingPath + "/") - if potentialProxtEndpoint != nil && !targetProxyEndpoint.Disabled { + if potentialProxtEndpoint != nil && !potentialProxtEndpoint.Disabled { //Missing tailing slash. Redirect to target proxy endpoint http.Redirect(w, r, r.RequestURI+"/", http.StatusTemporaryRedirect) return @@ -102,6 +102,13 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { /* Root Router Handling */ + + //Root access control based on default rule + blocked := h.handleAccessRouting("default", w, r) + if blocked { + return + } + //Clean up the request URI proxyingPath := strings.TrimSpace(r.RequestURI) if !strings.HasSuffix(proxyingPath, "/") { diff --git a/src/mod/dynamicproxy/access.go b/src/mod/dynamicproxy/access.go index b9c6857..441d0e5 100644 --- a/src/mod/dynamicproxy/access.go +++ b/src/mod/dynamicproxy/access.go @@ -21,6 +21,7 @@ func (h *ProxyHandler) handleAccessRouting(ruleID string, w http.ResponseWriter, w.Write([]byte("500 - Internal Server Error")) return true } + isBlocked, blockedReason := accessRequestBlocked(accessRule, h.Parent.Option.WebDirectory, w, r) if isBlocked { h.logRequest(r, false, 403, blockedReason, "") diff --git a/src/mod/dynamicproxy/endpoints.go b/src/mod/dynamicproxy/endpoints.go index a0f80fb..d403110 100644 --- a/src/mod/dynamicproxy/endpoints.go +++ b/src/mod/dynamicproxy/endpoints.go @@ -70,7 +70,8 @@ func (ep *ProxyEndpoint) AddUserDefinedHeader(key string, value string) error { func (ep *ProxyEndpoint) GetVirtualDirectoryHandlerFromRequestURI(requestURI string) *VirtualDirectoryEndpoint { for _, vdir := range ep.VirtualDirectories { if strings.HasPrefix(requestURI, vdir.MatchingPath) { - return vdir + thisVdir := vdir + return thisVdir } } return nil @@ -80,7 +81,8 @@ func (ep *ProxyEndpoint) GetVirtualDirectoryHandlerFromRequestURI(requestURI str func (ep *ProxyEndpoint) GetVirtualDirectoryRuleByMatchingPath(matchingPath string) *VirtualDirectoryEndpoint { for _, vdir := range ep.VirtualDirectories { if vdir.MatchingPath == matchingPath { - return vdir + thisVdir := vdir + return thisVdir } } return nil diff --git a/src/mod/email/email.go b/src/mod/email/email.go index 3191c7f..36946fc 100644 --- a/src/mod/email/email.go +++ b/src/mod/email/email.go @@ -13,18 +13,16 @@ import ( type Sender struct { Hostname string //E.g. mail.gandi.net - Domain string //E.g. arozos.com Port int //E.g. 587 Username string //Username of the email account Password string //Password of the email account SenderAddr string //e.g. admin@arozos.com } -//Create a new email sender object -func NewEmailSender(hostname string, domain string, port int, username string, password string, senderAddr string) *Sender { +// Create a new email sender object +func NewEmailSender(hostname string, port int, username string, password string, senderAddr string) *Sender { return &Sender{ Hostname: hostname, - Domain: domain, Port: port, Username: username, Password: password, @@ -33,13 +31,15 @@ func NewEmailSender(hostname string, domain string, port int, username string, p } /* - Send a email to a reciving addr - Example Usage: - SendEmail( - test@example.com, - "Free donuts", - "Come get your free donuts on this Sunday!" - ) +Send a email to a reciving addr +Example Usage: +SendEmail( + + test@example.com, + "Free donuts", + "Come get your free donuts on this Sunday!" + +) */ func (s *Sender) SendEmail(to string, subject string, content string) error { //Parse the email content @@ -50,7 +50,9 @@ func (s *Sender) SendEmail(to string, subject string, content string) error { content + "\n\n") //Login to the SMTP server - auth := smtp.PlainAuth("", s.Username+"@"+s.Domain, s.Password, s.Hostname) + //Username can be username (e.g. admin) or email (e.g. admin@example.com), depending on SMTP service provider + auth := smtp.PlainAuth("", s.Username, s.Password, s.Hostname) + err := smtp.SendMail(s.Hostname+":"+strconv.Itoa(s.Port), auth, s.SenderAddr, []string{to}, msg) if err != nil { return err diff --git a/src/mod/geodb/geodb.go b/src/mod/geodb/geodb.go index a25757a..8aed52d 100644 --- a/src/mod/geodb/geodb.go +++ b/src/mod/geodb/geodb.go @@ -83,6 +83,11 @@ func (s *Store) GetRequesterCountryISOCode(r *http.Request) string { if ipAddr == "" { return "" } + + if netutils.IsPrivateIP(ipAddr) { + return "LAN" + } + countryCode, err := s.ResolveCountryCodeFromIP(ipAddr) if err != nil { return "" diff --git a/src/mod/netutils/ipmatch.go b/src/mod/netutils/ipmatch.go index 2abd779..42608c5 100644 --- a/src/mod/netutils/ipmatch.go +++ b/src/mod/netutils/ipmatch.go @@ -93,6 +93,10 @@ func MatchIpCIDR(ip string, cidr string) bool { // Check if a ip is private IP range func IsPrivateIP(ipStr string) bool { + if ipStr == "127.0.0.1" || ipStr == "::1" { + //local loopback + return true + } ip := net.ParseIP(ipStr) if ip == nil { return false diff --git a/src/start.go b/src/start.go index f0a871e..acf3106 100644 --- a/src/start.go +++ b/src/start.go @@ -160,8 +160,17 @@ func startupSequence() { if err != nil { portInt = 8000 } + + hostName := *mdnsName + if hostName == "" { + hostName = "zoraxy_" + nodeUUID + } else { + //Trim off the suffix + hostName = strings.TrimSuffix(hostName, ".local") + } + mdnsScanner, err = mdns.NewMDNS(mdns.NetworkHost{ - HostName: "zoraxy_" + nodeUUID, + HostName: hostName, Port: portInt, Domain: "zoraxy.arozos.com", Model: "Network Gateway", diff --git a/src/web/components/stats.html b/src/web/components/stats.html index ba7f43f..4f650b0 100644 --- a/src/web/components/stats.html +++ b/src/web/components/stats.html @@ -765,8 +765,11 @@
Credentials for SMTP server authentications
-