mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-10-21 18:19:36 +02:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
72e5d3ce3f | ||
![]() |
5c8e4a7df1 | ||
![]() |
298444a53f | ||
![]() |
41cf0cc2c7 | ||
![]() |
863113a1b8 | ||
![]() |
aa9036fa8b |
@@ -1,3 +1,10 @@
|
||||
# v3.2.8 16 Oct 2025
|
||||
|
||||
+ Fixed wildcard certificate bug [#845](https://github.com/tobychui/zoraxy/issues/845) by [zen8841](https://github.com/zen8841)
|
||||
+ Move function:NormalizeDomain to netutils module by [zen8841](https://github.com/zen8841)
|
||||
+ Add support for Proxy Protocol V1 and V2 in streamproxy configuration by [jemmy1794](https://github.com/jemmy1794)
|
||||
+ Added user selectable versions for TLS
|
||||
|
||||
# v3.2.7 09 Oct 2025
|
||||
|
||||
+ Update Sidebar CSS by [Saeraphinx](https://github.com/Saeraphinx)
|
||||
|
@@ -44,7 +44,7 @@ import (
|
||||
const (
|
||||
/* Build Constants */
|
||||
SYSTEM_NAME = "Zoraxy"
|
||||
SYSTEM_VERSION = "3.2.8"
|
||||
SYSTEM_VERSION = "3.2.9"
|
||||
DEVELOPMENT_BUILD = false
|
||||
|
||||
/* System Constants */
|
||||
|
@@ -508,8 +508,8 @@ func (a *ACMEHandler) HandleRenewCertificate(w http.ResponseWriter, r *http.Requ
|
||||
dns = true
|
||||
}
|
||||
|
||||
// Default propagation timeout is 300 seconds
|
||||
propagationTimeout := 300
|
||||
// Default propagation timeout is 600 seconds (10 minutes)
|
||||
propagationTimeout := 600
|
||||
if dns {
|
||||
ppgTimeout, err := utils.PostPara(r, "ppgTimeout")
|
||||
if err == nil {
|
||||
|
@@ -51,6 +51,11 @@ func (router *Router) GetProxyEndpointFromHostname(hostname string) *ProxyEndpoi
|
||||
matchProxyEndpoints := []*ProxyEndpoint{}
|
||||
router.ProxyEndpoints.Range(func(k, v interface{}) bool {
|
||||
ep := v.(*ProxyEndpoint)
|
||||
if ep.Disabled {
|
||||
//Skip disabled endpoint
|
||||
return true
|
||||
}
|
||||
|
||||
match, err := filepath.Match(ep.RootOrMatchingDomain, hostname)
|
||||
if err != nil {
|
||||
//Bad pattern. Skip this rule
|
||||
@@ -83,12 +88,24 @@ func (router *Router) GetProxyEndpointFromHostname(hostname string) *ProxyEndpoi
|
||||
})
|
||||
|
||||
if len(matchProxyEndpoints) == 1 {
|
||||
//Only 1 match
|
||||
return matchProxyEndpoints[0]
|
||||
} else if len(matchProxyEndpoints) > 1 {
|
||||
//More than one match. Get the best match one
|
||||
sort.Slice(matchProxyEndpoints, func(i, j int) bool {
|
||||
return matchProxyEndpoints[i].RootOrMatchingDomain < matchProxyEndpoints[j].RootOrMatchingDomain
|
||||
// More than one match, pick one that is:
|
||||
// 1. longer RootOrMatchingDomain (more specific)
|
||||
// 2. fewer wildcard characters (* and ?) (more specific)
|
||||
// 3. fallback to lexicographic order
|
||||
sort.SliceStable(matchProxyEndpoints, func(i, j int) bool {
|
||||
a := matchProxyEndpoints[i].RootOrMatchingDomain
|
||||
b := matchProxyEndpoints[j].RootOrMatchingDomain
|
||||
if len(a) != len(b) {
|
||||
return len(a) > len(b)
|
||||
}
|
||||
aw := strings.Count(a, "*") + strings.Count(a, "?")
|
||||
bw := strings.Count(b, "*") + strings.Count(b, "?")
|
||||
if aw != bw {
|
||||
return aw < bw
|
||||
}
|
||||
return a < b
|
||||
})
|
||||
return matchProxyEndpoints[0]
|
||||
}
|
||||
@@ -110,13 +127,13 @@ func (router *Router) rewriteURL(rooturl string, requestURL string) string {
|
||||
// upstreamHostSwap check if this loopback to one of the proxy rule in the system. If yes, do a shortcut target swap
|
||||
// this prevents unnecessary external DNS lookup and connection, return true if swapped and request is already handled
|
||||
// by the loopback handler. Only continue if return is false
|
||||
func (h *ProxyHandler) upstreamHostSwap(w http.ResponseWriter, r *http.Request, selectedUpstream *loadbalance.Upstream) bool {
|
||||
func (h *ProxyHandler) upstreamHostSwap(w http.ResponseWriter, r *http.Request, selectedUpstream *loadbalance.Upstream, currentTarget *ProxyEndpoint) bool {
|
||||
upstreamHostname := selectedUpstream.OriginIpOrDomain
|
||||
if strings.Contains(upstreamHostname, ":") {
|
||||
upstreamHostname = strings.Split(upstreamHostname, ":")[0]
|
||||
}
|
||||
loopbackProxyEndpoint := h.Parent.GetProxyEndpointFromHostname(upstreamHostname)
|
||||
if loopbackProxyEndpoint != nil {
|
||||
if loopbackProxyEndpoint != nil && loopbackProxyEndpoint != currentTarget {
|
||||
//This is a loopback request. Swap the target to the loopback target
|
||||
//h.Parent.Option.Logger.PrintAndLog("proxy", "Detected a loopback request to self. Swap the target to "+loopbackProxyEndpoint.RootOrMatchingDomain, nil)
|
||||
if loopbackProxyEndpoint.IsEnabled() {
|
||||
@@ -147,7 +164,7 @@ func (h *ProxyHandler) hostRequest(w http.ResponseWriter, r *http.Request, targe
|
||||
}
|
||||
|
||||
/* Upstream Host Swap (use to detect loopback to self) */
|
||||
if h.upstreamHostSwap(w, r, selectedUpstream) {
|
||||
if h.upstreamHostSwap(w, r, selectedUpstream, target) {
|
||||
//Request handled by the loopback handler
|
||||
return
|
||||
}
|
||||
|
@@ -86,6 +86,7 @@ func (m *Manager) SetCertAsDefault(w http.ResponseWriter, r *http.Request) {
|
||||
//Check if the previous default cert exists. If yes, get its hostname from cert contents
|
||||
defaultPubKey := filepath.Join(m.CertStore, "default.key")
|
||||
defaultPriKey := filepath.Join(m.CertStore, "default.pem")
|
||||
defaultJSON := filepath.Join(m.CertStore, "default.json")
|
||||
if utils.FileExists(defaultPubKey) && utils.FileExists(defaultPriKey) {
|
||||
//Move the existing default cert to its original name
|
||||
certBytes, err := os.ReadFile(defaultPriKey)
|
||||
@@ -94,8 +95,15 @@ func (m *Manager) SetCertAsDefault(w http.ResponseWriter, r *http.Request) {
|
||||
if block != nil {
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err == nil {
|
||||
os.Rename(defaultPubKey, filepath.Join(m.CertStore, domainToFilename(cert.Subject.CommonName, "key")))
|
||||
os.Rename(defaultPriKey, filepath.Join(m.CertStore, domainToFilename(cert.Subject.CommonName, "pem")))
|
||||
originalKeyName := filepath.Join(m.CertStore, domainToFilename(cert.Subject.CommonName, "key"))
|
||||
originalPemName := filepath.Join(m.CertStore, domainToFilename(cert.Subject.CommonName, "pem"))
|
||||
originalJSONName := filepath.Join(m.CertStore, domainToFilename(cert.Subject.CommonName, "json"))
|
||||
|
||||
os.Rename(defaultPubKey, originalKeyName)
|
||||
os.Rename(defaultPriKey, originalPemName)
|
||||
if utils.FileExists(defaultJSON) {
|
||||
os.Rename(defaultJSON, originalJSONName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,9 +113,13 @@ func (m *Manager) SetCertAsDefault(w http.ResponseWriter, r *http.Request) {
|
||||
certname = filepath.Base(certname) //prevent path escape
|
||||
pubKey := filepath.Join(filepath.Join(m.CertStore), certname+".key")
|
||||
priKey := filepath.Join(filepath.Join(m.CertStore), certname+".pem")
|
||||
certJSON := filepath.Join(filepath.Join(m.CertStore), certname+".json")
|
||||
if utils.FileExists(pubKey) && utils.FileExists(priKey) {
|
||||
os.Rename(pubKey, filepath.Join(m.CertStore, "default.key"))
|
||||
os.Rename(priKey, filepath.Join(m.CertStore, "default.pem"))
|
||||
if utils.FileExists(certJSON) {
|
||||
os.Rename(certJSON, filepath.Join(m.CertStore, "default.json"))
|
||||
}
|
||||
utils.SendOK(w)
|
||||
|
||||
//Update cert list
|
||||
|
@@ -468,7 +468,7 @@
|
||||
defaultIntValue = 2;
|
||||
defaultMinValue = 1;
|
||||
}else if (key == "PropagationTimeout"){
|
||||
defaultIntValue = 120;
|
||||
defaultIntValue = 600;
|
||||
defaultMinValue = 30;
|
||||
}
|
||||
optionalFieldsHTML += (`<div class="ui fluid labeled dnsConfigField small input" key="${key}" style="margin-top: 0.2em;">
|
||||
|
Reference in New Issue
Block a user