mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-21 23:13:04 +02:00
Optimized UX and code structure
+ Added automatic self-sign certificate sniffing + Moved all constant into def.go + Added auto restart on port change when proxy server is running + Optimized slow search geoIP resolver by introducing new cache mechanism + Updated default incoming port to HTTPS instead of HTTP
This commit is contained in:
parent
0af8c67346
commit
015889851a
@ -8,6 +8,7 @@ import (
|
||||
"imuslab.com/zoraxy/mod/acme/acmedns"
|
||||
"imuslab.com/zoraxy/mod/acme/acmewizard"
|
||||
"imuslab.com/zoraxy/mod/auth"
|
||||
"imuslab.com/zoraxy/mod/dynamicproxy/domainsniff"
|
||||
"imuslab.com/zoraxy/mod/ipscan"
|
||||
"imuslab.com/zoraxy/mod/netstat"
|
||||
"imuslab.com/zoraxy/mod/netutils"
|
||||
@ -33,7 +34,7 @@ func RegisterHTTPProxyAPIs(authRouter *auth.RouterDef) {
|
||||
authRouter.HandleFunc("/api/proxy/setAlias", ReverseProxyHandleAlias)
|
||||
authRouter.HandleFunc("/api/proxy/del", DeleteProxyEndpoint)
|
||||
authRouter.HandleFunc("/api/proxy/updateCredentials", UpdateProxyBasicAuthCredentials)
|
||||
authRouter.HandleFunc("/api/proxy/tlscheck", HandleCheckSiteSupportTLS)
|
||||
authRouter.HandleFunc("/api/proxy/tlscheck", domainsniff.HandleCheckSiteSupportTLS)
|
||||
authRouter.HandleFunc("/api/proxy/setIncoming", HandleIncomingPortSet)
|
||||
authRouter.HandleFunc("/api/proxy/useHttpsRedirect", HandleUpdateHttpsRedirect)
|
||||
authRouter.HandleFunc("/api/proxy/listenPort80", HandleUpdatePort80Listener)
|
||||
|
@ -177,7 +177,10 @@ func handleListDomains(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Handle front-end toggling TLS mode
|
||||
func handleToggleTLSProxy(w http.ResponseWriter, r *http.Request) {
|
||||
currentTlsSetting := false
|
||||
currentTlsSetting := true //Default to true
|
||||
if dynamicProxyRouter.Option != nil {
|
||||
currentTlsSetting = dynamicProxyRouter.Option.UseTls
|
||||
}
|
||||
if sysdb.KeyExists("settings", "usetls") {
|
||||
sysdb.Read("settings", "usetls", ¤tTlsSetting)
|
||||
}
|
||||
|
41
src/def.go
41
src/def.go
@ -43,7 +43,7 @@ const (
|
||||
/* Build Constants */
|
||||
SYSTEM_NAME = "Zoraxy"
|
||||
SYSTEM_VERSION = "3.1.4"
|
||||
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"
|
||||
@ -55,6 +55,7 @@ const (
|
||||
MDNS_IDENTIFY_VENDOR = "imuslab.com"
|
||||
MDNS_SCAN_TIMEOUT = 30 /* Seconds */
|
||||
MDNS_SCAN_UPDATE_INTERVAL = 15 /* Minutes */
|
||||
GEODB_CACHE_CLEAR_INTERVAL = 15 /* Minutes */
|
||||
ACME_AUTORENEW_CONFIG_PATH = "./conf/acme_conf.json"
|
||||
CSRF_COOKIENAME = "zoraxy_csrf"
|
||||
LOG_PREFIX = "zr"
|
||||
@ -71,27 +72,29 @@ const (
|
||||
)
|
||||
|
||||
/* System Startup Flags */
|
||||
var webUIPort = flag.String("port", ":8000", "Management web interface listening port")
|
||||
var noauth = flag.Bool("noauth", false, "Disable authentication for management interface")
|
||||
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 runningInDocker = flag.Bool("docker", false, "Run Zoraxy in docker compatibility mode")
|
||||
var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)")
|
||||
var acmeCertAutoRenewDays = flag.Int("earlyrenew", 30, "Number of days to early renew a soon expiring certificate (days)")
|
||||
var enableHighSpeedGeoIPLookup = flag.Bool("fastgeoip", false, "Enable high speed geoip lookup, require 1GB extra memory (Not recommend for low end devices)")
|
||||
var staticWebServerRoot = flag.String("webroot", "./www", "Static web server root folder. Only allow chnage in start paramters")
|
||||
var allowWebFileManager = flag.Bool("webfm", true, "Enable web file manager for static web server root folder")
|
||||
var enableAutoUpdate = flag.Bool("cfgupgrade", true, "Enable auto config upgrade if breaking change is detected")
|
||||
var (
|
||||
webUIPort = flag.String("port", ":8000", "Management web interface listening port")
|
||||
noauth = flag.Bool("noauth", false, "Disable authentication for management interface")
|
||||
showver = flag.Bool("version", false, "Show version of this server")
|
||||
allowSshLoopback = flag.Bool("sshlb", false, "Allow loopback web ssh connection (DANGER)")
|
||||
allowMdnsScanning = flag.Bool("mdns", true, "Enable mDNS scanner and transponder")
|
||||
mdnsName = flag.String("mdnsname", "", "mDNS name, leave empty to use default (zoraxy_{node-uuid}.local)")
|
||||
ztAuthToken = flag.String("ztauth", "", "ZeroTier authtoken for the local node")
|
||||
ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port")
|
||||
runningInDocker = flag.Bool("docker", false, "Run Zoraxy in docker compatibility mode")
|
||||
acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)")
|
||||
acmeCertAutoRenewDays = flag.Int("earlyrenew", 30, "Number of days to early renew a soon expiring certificate (days)")
|
||||
enableHighSpeedGeoIPLookup = flag.Bool("fastgeoip", false, "Enable high speed geoip lookup, require 1GB extra memory (Not recommend for low end devices)")
|
||||
staticWebServerRoot = flag.String("webroot", "./www", "Static web server root folder. Only allow chnage in start paramters")
|
||||
allowWebFileManager = flag.Bool("webfm", true, "Enable web file manager for static web server root folder")
|
||||
enableAutoUpdate = flag.Bool("cfgupgrade", true, "Enable auto config upgrade if breaking change is detected")
|
||||
)
|
||||
|
||||
/* Global Variables and Handlers */
|
||||
var (
|
||||
nodeUUID = "generic" //System uuid, in uuidv4 format, load from database on startup
|
||||
nodeUUID = "generic" //System uuid in uuidv4 format, load from database on startup
|
||||
bootTime = time.Now().Unix()
|
||||
requireAuth = true /* Require authentication for webmin panel */
|
||||
requireAuth = true //Require authentication for webmin panel, override from flag
|
||||
|
||||
/*
|
||||
Binary Embedding File System
|
||||
@ -131,5 +134,5 @@ var (
|
||||
AnalyticLoader *analytic.DataLoader //Data loader for Zoraxy Analytic
|
||||
DockerUXOptimizer *dockerux.UXOptimizer //Docker user experience optimizer, community contribution only
|
||||
SystemWideLogger *logger.Logger //Logger for Zoraxy
|
||||
LogViewer *logviewer.Viewer
|
||||
LogViewer *logviewer.Viewer //Log viewer HTTP handlers
|
||||
)
|
||||
|
@ -210,8 +210,8 @@ func (a *AuthAgent) Logout(w http.ResponseWriter, r *http.Request) error {
|
||||
}
|
||||
session.Values["authenticated"] = false
|
||||
session.Values["username"] = nil
|
||||
session.Save(r, w)
|
||||
return nil
|
||||
session.Options.MaxAge = -1
|
||||
return session.Save(r, w)
|
||||
}
|
||||
|
||||
// Get the current session username from request
|
||||
@ -339,6 +339,7 @@ func (a *AuthAgent) CheckAuth(r *http.Request) bool {
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if user is authenticated
|
||||
if auth, ok := session.Values["authenticated"].(bool); !ok || !auth {
|
||||
return false
|
||||
|
@ -1,7 +1,6 @@
|
||||
package dynamicproxy
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -16,7 +15,7 @@ func (h *ProxyHandler) handleAccessRouting(ruleID string, w http.ResponseWriter,
|
||||
accessRule, err := h.Parent.Option.AccessController.GetAccessRuleByID(ruleID)
|
||||
if err != nil {
|
||||
//Unable to load access rule. Target rule not found?
|
||||
log.Println("[Proxy] Unable to load access rule: " + ruleID)
|
||||
h.Parent.Option.Logger.PrintAndLog("proxy-access", "Unable to load access rule: "+ruleID, err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte("500 - Internal Server Error"))
|
||||
return true
|
||||
|
@ -10,8 +10,14 @@ package domainsniff
|
||||
*/
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"imuslab.com/zoraxy/mod/utils"
|
||||
)
|
||||
|
||||
// Check if the domain is reachable and return err if not reachable
|
||||
@ -27,30 +33,114 @@ func DomainReachableWithError(domain string) error {
|
||||
}
|
||||
|
||||
// Check if a domain have TLS but it is self-signed or expired
|
||||
func DomainIsSelfSigned(domain string) (bool, error) {
|
||||
// Return false if sniff error
|
||||
func DomainIsSelfSigned(domain string) bool {
|
||||
//Extract the domain from URl in case the user input the full URL
|
||||
host, port, err := net.SplitHostPort(domain)
|
||||
if err != nil {
|
||||
host = domain
|
||||
} else {
|
||||
domain = host + ":" + port
|
||||
}
|
||||
if !strings.Contains(domain, ":") {
|
||||
domain = domain + ":443"
|
||||
}
|
||||
|
||||
//Get the certificate
|
||||
conn, err := net.Dial("tcp", domain)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
//Connect with TLS using secure verify
|
||||
tlsConn := tls.Client(conn, nil)
|
||||
err = tlsConn.Handshake()
|
||||
if err == nil {
|
||||
//This is a valid certificate
|
||||
fmt.Println()
|
||||
return false
|
||||
}
|
||||
|
||||
//Connect with TLS using insecure skip verify
|
||||
config := &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
tlsConn := tls.Client(conn, config)
|
||||
tlsConn = tls.Client(conn, config)
|
||||
err = tlsConn.Handshake()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
//Check if the certificate is self-signed
|
||||
cert := tlsConn.ConnectionState().PeerCertificates[0]
|
||||
return cert.Issuer.CommonName == cert.Subject.CommonName, nil
|
||||
//If the handshake is successful, this is a self-signed certificate
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Check if domain reachable
|
||||
func DomainReachable(domain string) bool {
|
||||
return DomainReachableWithError(domain) == nil
|
||||
}
|
||||
|
||||
// Check if domain is served by a web server using HTTPS
|
||||
func DomainUsesTLS(targetURL string) bool {
|
||||
//Check if the site support https
|
||||
httpsUrl := fmt.Sprintf("https://%s", targetURL)
|
||||
httpUrl := fmt.Sprintf("http://%s", targetURL)
|
||||
|
||||
client := http.Client{Timeout: 5 * time.Second}
|
||||
|
||||
resp, err := client.Head(httpsUrl)
|
||||
if err == nil && resp.StatusCode == http.StatusOK {
|
||||
return true
|
||||
}
|
||||
|
||||
resp, err = client.Head(httpUrl)
|
||||
if err == nil && resp.StatusCode == http.StatusOK {
|
||||
return false
|
||||
}
|
||||
|
||||
//If the site is not reachable, return false
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
Request Handlers
|
||||
*/
|
||||
//Check if site support TLS
|
||||
//Pass in ?selfsignchk=true to also check for self-signed certificate
|
||||
func HandleCheckSiteSupportTLS(w http.ResponseWriter, r *http.Request) {
|
||||
targetURL, err := utils.PostPara(r, "url")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid url given")
|
||||
return
|
||||
}
|
||||
|
||||
//If the selfsign flag is set, also chec for self-signed certificate
|
||||
_, err = utils.PostBool(r, "selfsignchk")
|
||||
if err == nil {
|
||||
//Return the https and selfsign status
|
||||
type result struct {
|
||||
Protocol string `json:"protocol"`
|
||||
SelfSign bool `json:"selfsign"`
|
||||
}
|
||||
|
||||
scanResult := result{Protocol: "http", SelfSign: false}
|
||||
|
||||
if DomainUsesTLS(targetURL) {
|
||||
scanResult.Protocol = "https"
|
||||
if DomainIsSelfSigned(targetURL) {
|
||||
scanResult.SelfSign = true
|
||||
}
|
||||
}
|
||||
|
||||
js, _ := json.Marshal(scanResult)
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
return
|
||||
}
|
||||
|
||||
if DomainUsesTLS(targetURL) {
|
||||
js, _ := json.Marshal("https")
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
return
|
||||
} else {
|
||||
js, _ := json.Marshal("http")
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ func (router *Router) Restart() error {
|
||||
return err
|
||||
}
|
||||
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
time.Sleep(800 * time.Millisecond)
|
||||
// Start the server
|
||||
err = router.StartProxyService()
|
||||
if err != nil {
|
||||
|
@ -3,6 +3,7 @@ package geodb
|
||||
import (
|
||||
_ "embed"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"imuslab.com/zoraxy/mod/database"
|
||||
"imuslab.com/zoraxy/mod/netutils"
|
||||
@ -15,17 +16,22 @@ var geoipv4 []byte //Geodb dataset for ipv4
|
||||
var geoipv6 []byte //Geodb dataset for ipv6
|
||||
|
||||
type Store struct {
|
||||
geodb [][]string //Parsed geodb list
|
||||
geodbIpv6 [][]string //Parsed geodb list for ipv6
|
||||
geotrie *trie
|
||||
geotrieIpv6 *trie
|
||||
sysdb *database.Database
|
||||
option *StoreOptions
|
||||
geodb [][]string //Parsed geodb list
|
||||
geodbIpv6 [][]string //Parsed geodb list for ipv6
|
||||
geotrie *trie
|
||||
geotrieIpv6 *trie
|
||||
sysdb *database.Database
|
||||
slowLookupCacheIpv4 map[string]string //Cache for slow lookup
|
||||
slowLookupCacheIpv6 map[string]string //Cache for slow lookup
|
||||
cacheClearTicker *time.Ticker //Ticker for clearing cache
|
||||
cacheClearTickerStopChan chan bool //Stop channel for cache clear ticker
|
||||
option *StoreOptions
|
||||
}
|
||||
|
||||
type StoreOptions struct {
|
||||
AllowSlowIpv4LookUp bool
|
||||
AllowSloeIpv6Lookup bool
|
||||
AllowSlowIpv4LookUp bool
|
||||
AllowSlowIpv6Lookup bool
|
||||
SlowLookupCacheClearInterval time.Duration //Clear slow lookup cache interval
|
||||
}
|
||||
|
||||
type CountryInfo struct {
|
||||
@ -50,18 +56,44 @@ func NewGeoDb(sysdb *database.Database, option *StoreOptions) (*Store, error) {
|
||||
}
|
||||
|
||||
var ipv6Trie *trie
|
||||
if !option.AllowSloeIpv6Lookup {
|
||||
if !option.AllowSlowIpv6Lookup {
|
||||
ipv6Trie = constrctTrieTree(parsedGeoDataIpv6)
|
||||
}
|
||||
|
||||
return &Store{
|
||||
geodb: parsedGeoData,
|
||||
geotrie: ipv4Trie,
|
||||
geodbIpv6: parsedGeoDataIpv6,
|
||||
geotrieIpv6: ipv6Trie,
|
||||
sysdb: sysdb,
|
||||
option: option,
|
||||
}, nil
|
||||
if option.SlowLookupCacheClearInterval == 0 {
|
||||
option.SlowLookupCacheClearInterval = 15 * time.Minute
|
||||
}
|
||||
|
||||
//Create a new store
|
||||
thisGeoDBStore := &Store{
|
||||
geodb: parsedGeoData,
|
||||
geotrie: ipv4Trie,
|
||||
geodbIpv6: parsedGeoDataIpv6,
|
||||
geotrieIpv6: ipv6Trie,
|
||||
sysdb: sysdb,
|
||||
slowLookupCacheIpv4: make(map[string]string),
|
||||
slowLookupCacheIpv6: make(map[string]string),
|
||||
cacheClearTicker: time.NewTicker(option.SlowLookupCacheClearInterval),
|
||||
cacheClearTickerStopChan: make(chan bool),
|
||||
option: option,
|
||||
}
|
||||
|
||||
//Start cache clear ticker
|
||||
if option.AllowSlowIpv4LookUp || option.AllowSlowIpv6Lookup {
|
||||
go func(store *Store) {
|
||||
for {
|
||||
select {
|
||||
case <-store.cacheClearTickerStopChan:
|
||||
return
|
||||
case <-thisGeoDBStore.cacheClearTicker.C:
|
||||
thisGeoDBStore.slowLookupCacheIpv4 = make(map[string]string)
|
||||
thisGeoDBStore.slowLookupCacheIpv6 = make(map[string]string)
|
||||
}
|
||||
}
|
||||
}(thisGeoDBStore)
|
||||
}
|
||||
|
||||
return thisGeoDBStore, nil
|
||||
}
|
||||
|
||||
func (s *Store) ResolveCountryCodeFromIP(ipstring string) (*CountryInfo, error) {
|
||||
@ -73,8 +105,12 @@ func (s *Store) ResolveCountryCodeFromIP(ipstring string) (*CountryInfo, error)
|
||||
|
||||
}
|
||||
|
||||
// Close the store
|
||||
func (s *Store) Close() {
|
||||
|
||||
if s.option.AllowSlowIpv4LookUp || s.option.AllowSlowIpv6Lookup {
|
||||
//Stop cache clear ticker
|
||||
s.cacheClearTickerStopChan <- true
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Store) GetRequesterCountryISOCode(r *http.Request) string {
|
||||
|
@ -44,6 +44,7 @@ func TestResolveCountryCodeFromIP(t *testing.T) {
|
||||
store, err := geodb.NewGeoDb(nil, &geodb.StoreOptions{
|
||||
false,
|
||||
true,
|
||||
0,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("error creating store: %v", err)
|
||||
|
@ -56,6 +56,12 @@ func (s *Store) slowSearchIpv4(ipAddr string) string {
|
||||
if isReservedIP(ipAddr) {
|
||||
return ""
|
||||
}
|
||||
|
||||
//Check if already in cache
|
||||
if cc, ok := s.slowLookupCacheIpv4[ipAddr]; ok {
|
||||
return cc
|
||||
}
|
||||
|
||||
for _, ipRange := range s.geodb {
|
||||
startIp := ipRange[0]
|
||||
endIp := ipRange[1]
|
||||
@ -63,6 +69,8 @@ func (s *Store) slowSearchIpv4(ipAddr string) string {
|
||||
|
||||
inRange, _ := isIPv4InRange(startIp, endIp, ipAddr)
|
||||
if inRange {
|
||||
//Add to cache
|
||||
s.slowLookupCacheIpv4[ipAddr] = cc
|
||||
return cc
|
||||
}
|
||||
}
|
||||
@ -73,6 +81,12 @@ func (s *Store) slowSearchIpv6(ipAddr string) string {
|
||||
if isReservedIP(ipAddr) {
|
||||
return ""
|
||||
}
|
||||
|
||||
//Check if already in cache
|
||||
if cc, ok := s.slowLookupCacheIpv6[ipAddr]; ok {
|
||||
return cc
|
||||
}
|
||||
|
||||
for _, ipRange := range s.geodbIpv6 {
|
||||
startIp := ipRange[0]
|
||||
endIp := ipRange[1]
|
||||
@ -80,6 +94,8 @@ func (s *Store) slowSearchIpv6(ipAddr string) string {
|
||||
|
||||
inRange, _ := isIPv6InRange(startIp, endIp, ipAddr)
|
||||
if inRange {
|
||||
//Add to cache
|
||||
s.slowLookupCacheIpv6[ipAddr] = cc
|
||||
return cc
|
||||
}
|
||||
}
|
||||
|
@ -27,18 +27,18 @@ func ReverseProxtInit() {
|
||||
/*
|
||||
Load Reverse Proxy Global Settings
|
||||
*/
|
||||
inboundPort := 80
|
||||
inboundPort := 443
|
||||
if sysdb.KeyExists("settings", "inbound") {
|
||||
sysdb.Read("settings", "inbound", &inboundPort)
|
||||
SystemWideLogger.Println("Serving inbound port ", inboundPort)
|
||||
} else {
|
||||
SystemWideLogger.Println("Inbound port not set. Using default (80)")
|
||||
SystemWideLogger.Println("Inbound port not set. Using default (443)")
|
||||
}
|
||||
|
||||
useTls := false
|
||||
useTls := true
|
||||
sysdb.Read("settings", "usetls", &useTls)
|
||||
if useTls {
|
||||
SystemWideLogger.Println("TLS mode enabled. Serving proxxy request with TLS")
|
||||
SystemWideLogger.Println("TLS mode enabled. Serving proxy request with TLS")
|
||||
} else {
|
||||
SystemWideLogger.Println("TLS mode disabled. Serving proxy request with plain http")
|
||||
}
|
||||
@ -59,7 +59,7 @@ func ReverseProxtInit() {
|
||||
SystemWideLogger.Println("Development mode disabled. Proxying with default Cache Control policy")
|
||||
}
|
||||
|
||||
listenOnPort80 := false
|
||||
listenOnPort80 := true
|
||||
sysdb.Read("settings", "listenP80", &listenOnPort80)
|
||||
if listenOnPort80 {
|
||||
SystemWideLogger.Println("Port 80 listener enabled")
|
||||
@ -67,7 +67,7 @@ func ReverseProxtInit() {
|
||||
SystemWideLogger.Println("Port 80 listener disabled")
|
||||
}
|
||||
|
||||
forceHttpsRedirect := false
|
||||
forceHttpsRedirect := true
|
||||
sysdb.Read("settings", "redirect", &forceHttpsRedirect)
|
||||
if forceHttpsRedirect {
|
||||
SystemWideLogger.Println("Force HTTPS mode enabled")
|
||||
@ -1085,6 +1085,7 @@ func HandleIncomingPortSet(w http.ResponseWriter, r *http.Request) {
|
||||
if dynamicProxyRouter.Running {
|
||||
dynamicProxyRouter.StopProxyService()
|
||||
dynamicProxyRouter.Option.Port = newIncomingPortInt
|
||||
time.Sleep(1 * time.Second) //Fixed start fail issue
|
||||
dynamicProxyRouter.StartProxyService()
|
||||
} else {
|
||||
//Only change setting but not starting the proxy service
|
||||
|
@ -103,8 +103,9 @@ func startupSequence() {
|
||||
|
||||
//Create a geodb store
|
||||
geodbStore, err = geodb.NewGeoDb(sysdb, &geodb.StoreOptions{
|
||||
AllowSlowIpv4LookUp: !*enableHighSpeedGeoIPLookup,
|
||||
AllowSloeIpv6Lookup: !*enableHighSpeedGeoIPLookup,
|
||||
AllowSlowIpv4LookUp: !*enableHighSpeedGeoIPLookup,
|
||||
AllowSlowIpv6Lookup: !*enableHighSpeedGeoIPLookup,
|
||||
SlowLookupCacheClearInterval: GEODB_CACHE_CLEAR_INTERVAL * time.Minute,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -295,15 +295,25 @@
|
||||
//Automatic check if the site require TLS and check the checkbox if needed
|
||||
function autoCheckTls(targetDomain){
|
||||
$.cjax({
|
||||
url: "/api/proxy/tlscheck",
|
||||
url: "/api/proxy/tlscheck?selfsignchk=true",
|
||||
data: {url: targetDomain},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
msgbox(data.error, false);
|
||||
}else if (data == "https"){
|
||||
$("#reqTls").parent().checkbox("set checked");
|
||||
}else if (data == "http"){
|
||||
$("#reqTls").parent().checkbox("set unchecked");
|
||||
}else{
|
||||
//Check if the site require TLS
|
||||
if (data.protocol == "https"){
|
||||
$("#reqTls").parent().checkbox("set checked");
|
||||
}else if (data.protocol == "http"){
|
||||
$("#reqTls").parent().checkbox("set unchecked");
|
||||
}
|
||||
//Check if the site is using self-signed cert
|
||||
if (data.selfsign){
|
||||
$("#skipTLSValidation").parent().checkbox("set checked");
|
||||
}else{
|
||||
$("#skipTLSValidation").parent().checkbox("set unchecked");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -73,25 +73,27 @@
|
||||
<p>Inbound Port (Reverse Proxy Listening Port)</p>
|
||||
<div class="ui action fluid notloopbackOnly input" tourstep="incomingPort">
|
||||
<small id="applyButtonReminder">Click "Apply" button to confirm listening port changes</small>
|
||||
<input type="text" id="incomingPort" placeholder="Incoming Port" value="80">
|
||||
<input type="text" id="incomingPort" placeholder="Incoming Port" value="443">
|
||||
<button class="ui green notloopbackOnly button" style="background: linear-gradient(60deg, #27e7ff, #00ca52);" onclick="handlePortChange();"><i class="ui checkmark icon"></i> Apply</button>
|
||||
</div>
|
||||
<br>
|
||||
<div id="tls" class="ui toggle notloopbackOnly checkbox">
|
||||
<input type="checkbox">
|
||||
<label>Use TLS to serve proxy request</label>
|
||||
<label>Use TLS to serve proxy request<br>
|
||||
<small>Also known as HTTPS mode</small></label>
|
||||
</div>
|
||||
<br>
|
||||
<div id="listenP80" class="ui toggle notloopbackOnly tlsEnabledOnly checkbox" style="margin-top: 0.6em;" >
|
||||
<div id="listenP80" class="ui toggle notloopbackOnly tlsEnabledOnly checkbox" style="margin-top: 0.4em;" >
|
||||
<input type="checkbox">
|
||||
<label>Enable HTTP server on port 80<br>
|
||||
<small>(Only apply when TLS enabled and not using port 80)</small></label>
|
||||
<small>Accept HTTP requests even if you are using HTTPS mode</small></label>
|
||||
</div>
|
||||
<br>
|
||||
<div tourstep="forceHttpsRedirect" style="display: inline-block;">
|
||||
<div id="redirect" class="ui toggle notloopbackOnly tlsEnabledOnly checkbox" style="margin-top: 0.6em; padding-left: 2em;">
|
||||
<div id="redirect" class="ui toggle notloopbackOnly tlsEnabledOnly checkbox" style="margin-top: 0.4em;">
|
||||
<input type="checkbox">
|
||||
<label>Force redirect HTTP request to HTTPS</label>
|
||||
<label>Force redirect HTTP request to HTTPS<br>
|
||||
<small>Redirect web traffic from port 80 to 443, require enabling HTTP server on port 80</small></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui basic segment advanceoptions">
|
||||
@ -359,10 +361,10 @@
|
||||
return;
|
||||
}
|
||||
if (enabled){
|
||||
$("#redirect").show();
|
||||
//$("#redirect").show();
|
||||
msgbox("Port 80 listener enabled");
|
||||
}else{
|
||||
$("#redirect").hide();
|
||||
//$("#redirect").hide();
|
||||
msgbox("Port 80 listener disabled");
|
||||
}
|
||||
}
|
||||
@ -400,10 +402,10 @@
|
||||
$.get("/api/proxy/listenPort80", function(data){
|
||||
if (data){
|
||||
$("#listenP80").checkbox("set checked");
|
||||
$("#redirect").show();
|
||||
//$("#redirect").show();
|
||||
}else{
|
||||
$("#listenP80").checkbox("set unchecked");
|
||||
$("#redirect").hide();
|
||||
//$("#redirect").hide();
|
||||
}
|
||||
|
||||
$("#listenP80").find("input").on("change", function(){
|
||||
|
@ -191,14 +191,19 @@
|
||||
var targetDomain = $("#virtualDirectoryDomain").val().trim();
|
||||
if (targetDomain != ""){
|
||||
$.cjax({
|
||||
url: "/api/proxy/tlscheck",
|
||||
url: "/api/proxy/tlscheck?selfsignchk=true",
|
||||
data: {url: targetDomain},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
|
||||
}else if (data == "https"){
|
||||
}else if (data.protocol == "https"){
|
||||
$("#vdReqTls").parent().checkbox("set checked");
|
||||
}else if (data == "http"){
|
||||
if (data.selfsign){
|
||||
$("#vdSkipTLSValidation").parent().checkbox("set checked");
|
||||
}else{
|
||||
$("#vdSkipTLSValidation").parent().checkbox("set unchecked");
|
||||
}
|
||||
}else if (data.protocol == "http"){
|
||||
$("#vdReqTls").parent().checkbox("set unchecked");
|
||||
}
|
||||
}
|
||||
|
@ -18,11 +18,9 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"imuslab.com/zoraxy/mod/dynamicproxy"
|
||||
"imuslab.com/zoraxy/mod/dynamicproxy/loadbalance"
|
||||
@ -32,39 +30,6 @@ import (
|
||||
"imuslab.com/zoraxy/mod/wakeonlan"
|
||||
)
|
||||
|
||||
/*
|
||||
Proxy Utils
|
||||
*/
|
||||
//Check if site support TLS
|
||||
func HandleCheckSiteSupportTLS(w http.ResponseWriter, r *http.Request) {
|
||||
targetURL, err := utils.PostPara(r, "url")
|
||||
if err != nil {
|
||||
utils.SendErrorResponse(w, "invalid url given")
|
||||
return
|
||||
}
|
||||
|
||||
httpsUrl := fmt.Sprintf("https://%s", targetURL)
|
||||
httpUrl := fmt.Sprintf("http://%s", targetURL)
|
||||
|
||||
client := http.Client{Timeout: 5 * time.Second}
|
||||
|
||||
resp, err := client.Head(httpsUrl)
|
||||
if err == nil && resp.StatusCode == http.StatusOK {
|
||||
js, _ := json.Marshal("https")
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
return
|
||||
}
|
||||
|
||||
resp, err = client.Head(httpUrl)
|
||||
if err == nil && resp.StatusCode == http.StatusOK {
|
||||
js, _ := json.Marshal("http")
|
||||
utils.SendJSONResponse(w, string(js))
|
||||
return
|
||||
}
|
||||
|
||||
utils.SendErrorResponse(w, "invalid url given")
|
||||
}
|
||||
|
||||
/*
|
||||
Statistic Summary
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user