zoraxy-waf/hosts.go

76 lines
1.7 KiB
Go

package main
import (
"encoding/json"
"log"
"os"
"path/filepath"
"strings"
"sync"
)
// proxyRule is the minimal structure we need from Zoraxy's proxy config files.
type proxyRule struct {
Domain string `json:"RootOrMatchingDomain"`
ActiveOrigins []struct {
Origin string `json:"OriginIpOrDomain"`
} `json:"ActiveOrigins"`
Disabled bool `json:"Disabled"`
}
// hostMap maps request Host headers to backend URLs.
var (
hostMap = make(map[string]string)
hostMapMu sync.RWMutex
)
// loadHostMap reads Zoraxy proxy configs and builds a host→backend map.
func loadHostMap() {
hostMapMu.Lock()
defer hostMapMu.Unlock()
hostMap = make(map[string]string)
proxyDir := "/opt/zoraxy/conf/proxy"
entries, err := os.ReadDir(proxyDir)
if err != nil {
log.Printf("WARN: cannot read proxy configs: %v", err)
return
}
for _, entry := range entries {
if !strings.HasSuffix(entry.Name(), ".config") {
continue
}
path := filepath.Join(proxyDir, entry.Name())
data, err := os.ReadFile(path)
if err != nil {
continue
}
var rule proxyRule
if err := json.Unmarshal(data, &rule); err != nil {
continue
}
if rule.Disabled || len(rule.ActiveOrigins) == 0 {
continue
}
hostMap[strings.ToLower(rule.Domain)] = rule.ActiveOrigins[0].Origin
}
log.Printf("Firewall: loaded %d proxy backends", len(hostMap))
}
// resolveBackend finds the backend URL for a given Host header.
// Falls back to the configured BackendURL if no match.
func resolveBackend(host string) string {
hostMapMu.RLock()
defer hostMapMu.RUnlock()
if backend, ok := hostMap[strings.ToLower(host)]; ok {
return backend
}
if backend, ok := hostMap[strings.ToLower(strings.Split(host, ":")[0])]; ok {
return backend
}
// Fallback
return getConfig().BackendURL
}