mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-08-03 11:56:43 +02:00

- Added certificate resolve viewer on HTTP proxy rule editor - Exposed SNI options (wip) - Code optimize
155 lines
4.6 KiB
Go
155 lines
4.6 KiB
Go
package dynamicproxy
|
|
|
|
import (
|
|
"errors"
|
|
"log"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
"imuslab.com/zoraxy/mod/dynamicproxy/dpcore"
|
|
"imuslab.com/zoraxy/mod/utils"
|
|
)
|
|
|
|
/*
|
|
Dynamic Proxy Router Functions
|
|
|
|
This script handle the proxy rules router spawning
|
|
and preparation
|
|
*/
|
|
|
|
// Prepare proxy route generate a proxy handler service object for your endpoint
|
|
func (router *Router) PrepareProxyRoute(endpoint *ProxyEndpoint) (*ProxyEndpoint, error) {
|
|
for _, thisOrigin := range endpoint.ActiveOrigins {
|
|
//Create the proxy routing handler
|
|
err := thisOrigin.StartProxy()
|
|
if err != nil {
|
|
log.Println("Unable to setup upstream " + thisOrigin.OriginIpOrDomain + ": " + err.Error())
|
|
continue
|
|
}
|
|
}
|
|
|
|
endpoint.parent = router
|
|
|
|
//Prepare proxy routing handler for each of the virtual directories
|
|
for _, vdir := range endpoint.VirtualDirectories {
|
|
domain := vdir.Domain
|
|
if len(domain) == 0 {
|
|
//invalid vdir
|
|
continue
|
|
}
|
|
if domain[len(domain)-1:] == "/" {
|
|
domain = domain[:len(domain)-1]
|
|
}
|
|
|
|
//Parse the web proxy endpoint
|
|
webProxyEndpoint := domain
|
|
if !strings.HasPrefix("http://", domain) && !strings.HasPrefix("https://", domain) {
|
|
//TLS is not hardcoded in proxy target domain
|
|
if vdir.RequireTLS {
|
|
webProxyEndpoint = "https://" + webProxyEndpoint
|
|
} else {
|
|
webProxyEndpoint = "http://" + webProxyEndpoint
|
|
}
|
|
}
|
|
|
|
path, err := url.Parse(webProxyEndpoint)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
proxy := dpcore.NewDynamicProxyCore(path, vdir.MatchingPath, &dpcore.DpcoreOptions{
|
|
IgnoreTLSVerification: vdir.SkipCertValidations,
|
|
FlushInterval: 500 * time.Millisecond,
|
|
})
|
|
vdir.proxy = proxy
|
|
vdir.parent = endpoint
|
|
}
|
|
|
|
return endpoint, nil
|
|
}
|
|
|
|
// Add Proxy Route to current runtime. Call to PrepareProxyRoute before adding to runtime
|
|
func (router *Router) AddProxyRouteToRuntime(endpoint *ProxyEndpoint) error {
|
|
lookupHostname := strings.ToLower(endpoint.RootOrMatchingDomain)
|
|
if len(endpoint.ActiveOrigins) == 0 {
|
|
//There are no active origins. No need to check for ready
|
|
router.ProxyEndpoints.Store(lookupHostname, endpoint)
|
|
return nil
|
|
}
|
|
if !router.loadBalancer.UpstreamsReady(endpoint.ActiveOrigins) {
|
|
//This endpoint is not prepared
|
|
return errors.New("proxy endpoint not ready. Use PrepareProxyRoute before adding to runtime")
|
|
}
|
|
// Push record into running subdomain endpoints
|
|
router.ProxyEndpoints.Store(lookupHostname, endpoint)
|
|
return nil
|
|
}
|
|
|
|
// Set given Proxy Route as Root. Call to PrepareProxyRoute before adding to runtime
|
|
func (router *Router) SetProxyRouteAsRoot(endpoint *ProxyEndpoint) error {
|
|
if !router.loadBalancer.UpstreamsReady(endpoint.ActiveOrigins) {
|
|
//This endpoint is not prepared
|
|
return errors.New("proxy endpoint not ready. Use PrepareProxyRoute before adding to runtime")
|
|
}
|
|
// Push record into running root endpoints
|
|
router.Root = endpoint
|
|
return nil
|
|
}
|
|
|
|
// ProxyEndpoint remove provide global access by key
|
|
func (router *Router) RemoveProxyEndpointByRootname(rootnameOrMatchingDomain string) error {
|
|
targetEpt, err := router.LoadProxy(rootnameOrMatchingDomain)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return targetEpt.Remove()
|
|
}
|
|
|
|
// GetProxyEndpointById retrieves a proxy endpoint by its ID from the Router's ProxyEndpoints map.
|
|
// It returns the ProxyEndpoint if found, or an error if not found.
|
|
func (h *Router) GetProxyEndpointById(searchingDomain string, includeAlias bool) (*ProxyEndpoint, error) {
|
|
var found *ProxyEndpoint
|
|
h.ProxyEndpoints.Range(func(key, value interface{}) bool {
|
|
proxy, ok := value.(*ProxyEndpoint)
|
|
if ok && (proxy.RootOrMatchingDomain == searchingDomain || (includeAlias && utils.StringInArray(proxy.MatchingDomainAlias, searchingDomain))) {
|
|
found = proxy
|
|
return false // stop iteration
|
|
}
|
|
return true // continue iteration
|
|
})
|
|
if found != nil {
|
|
return found, nil
|
|
}
|
|
return nil, errors.New("proxy rule with given id not found")
|
|
}
|
|
|
|
func (h *Router) GetProxyEndpointByAlias(alias string) (*ProxyEndpoint, error) {
|
|
var found *ProxyEndpoint
|
|
h.ProxyEndpoints.Range(func(key, value interface{}) bool {
|
|
proxy, ok := value.(*ProxyEndpoint)
|
|
if !ok {
|
|
return true
|
|
}
|
|
//Also check for wildcard aliases that matches the alias
|
|
for _, thisAlias := range proxy.MatchingDomainAlias {
|
|
if ok && thisAlias == alias {
|
|
found = proxy
|
|
return false // stop iteration
|
|
} else if ok && strings.HasPrefix(thisAlias, "*") {
|
|
//Check if the alias matches a wildcard alias
|
|
if strings.HasSuffix(alias, thisAlias[1:]) {
|
|
found = proxy
|
|
return false // stop iteration
|
|
}
|
|
}
|
|
}
|
|
return true // continue iteration
|
|
})
|
|
if found != nil {
|
|
return found, nil
|
|
}
|
|
return nil, errors.New("proxy rule with given alias not found")
|
|
}
|