Skip to content

Commit

Permalink
Updates v2.6 experimental build
Browse files Browse the repository at this point in the history
+ Basic auth
+ Support TLS verification skip (for self signed certs)
+ Added trend analysis
+ Added referer and file type analysis
+ Added cert expire day display
+ Moved subdomain proxy logic to dpcore
  • Loading branch information
tobychui committed May 27, 2023
1 parent edd19e2 commit 5952a1b
Show file tree
Hide file tree
Showing 18 changed files with 792 additions and 145 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ src/conf/*
src/ReverseProxy_*_*
src/Zoraxy_*_*
src/certs/*
src/rules/*
src/rules/*
src/README.md
24 changes: 23 additions & 1 deletion src/cert.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package main

import (
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"io"
"log"
Expand Down Expand Up @@ -41,21 +43,41 @@ func handleListCertificate(w http.ResponseWriter, r *http.Request) {
type CertInfo struct {
Domain string
LastModifiedDate string
ExpireDate string
}

results := []*CertInfo{}

for _, filename := range filenames {
fileInfo, err := os.Stat(filepath.Join(tlsCertManager.CertStore, filename+".crt"))
certFilepath := filepath.Join(tlsCertManager.CertStore, filename+".crt")
//keyFilepath := filepath.Join(tlsCertManager.CertStore, filename+".key")
fileInfo, err := os.Stat(certFilepath)
if err != nil {
utils.SendErrorResponse(w, "invalid domain certificate discovered: "+filename)
return
}
modifiedTime := fileInfo.ModTime().Format("2006-01-02 15:04:05")

certExpireTime := "Unknown"
certBtyes, err := os.ReadFile(certFilepath)
if err != nil {
//Unable to load this file
continue
} else {
//Cert loaded. Check its expire time
block, _ := pem.Decode(certBtyes)
if block != nil {
cert, err := x509.ParseCertificate(block.Bytes)
if err == nil {
certExpireTime = cert.NotAfter.Format("2006-01-02 15:04:05")
}
}
}

thisCertInfo := CertInfo{
Domain: filename,
LastModifiedDate: modifiedTime,
ExpireDate: certExpireTime,
}

results = append(results, &thisCertInfo)
Expand Down
25 changes: 12 additions & 13 deletions src/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"path/filepath"
"strings"

"imuslab.com/zoraxy/mod/dynamicproxy"
"imuslab.com/zoraxy/mod/utils"
)

Expand All @@ -19,23 +20,22 @@ import (
*/

type Record struct {
ProxyType string
Rootname string
ProxyTarget string
UseTLS bool
ProxyType string
Rootname string
ProxyTarget string
UseTLS bool
SkipTlsValidation bool
RequireBasicAuth bool
BasicAuthCredentials []*dynamicproxy.BasicAuthCredentials
}

func SaveReverseProxyConfig(ptype string, rootname string, proxyTarget string, useTLS bool) error {
func SaveReverseProxyConfig(proxyConfigRecord *Record) error {
//TODO: Make this accept new def types
os.MkdirAll("conf", 0775)
filename := getFilenameFromRootName(rootname)
filename := getFilenameFromRootName(proxyConfigRecord.Rootname)

//Generate record
thisRecord := Record{
ProxyType: ptype,
Rootname: rootname,
ProxyTarget: proxyTarget,
UseTLS: useTLS,
}
thisRecord := proxyConfigRecord

//Write to file
js, _ := json.MarshalIndent(thisRecord, "", " ")
Expand Down Expand Up @@ -67,7 +67,6 @@ func LoadReverseProxyConfig(filename string) (*Record, error) {
}

//Unmarshal the content into config

err = json.Unmarshal(configContent, &thisRecord)
if err != nil {
return &thisRecord, err
Expand Down
2 changes: 1 addition & 1 deletion src/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ var ztAuthToken = flag.String("ztauth", "", "ZeroTier authtoken for the local no
var ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port")
var (
name = "Zoraxy"
version = "2.5"
version = "2.6"
nodeUUID = "generic"
development = false //Set this to false to use embedded web fs

Expand Down
36 changes: 33 additions & 3 deletions src/mod/dynamicproxy/Server.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,19 @@ import (
Server.go
Main server for dynamic proxy core
Routing Handler Priority (High to Low)
- Blacklist
- Whitelist
- Redirectable
- Subdomain Routing
- Vitrual Directory Routing
*/

func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
/*
General Access Check
*/
//Check if this ip is in blacklist
clientIpAddr := geodb.GetRequesterIP(r)
if h.Parent.Option.GeodbStore.IsBlacklisted(clientIpAddr) {
Expand All @@ -30,6 +40,9 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}

/*
Redirection Routing
*/
//Check if this is a redirection url
if h.Parent.Option.RedirectRuleTable.IsRedirectable(r) {
statusCode := h.Parent.Option.RedirectRuleTable.HandleRedirect(w, r)
Expand All @@ -53,33 +66,50 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
domainOnly = hostPath[0]
}

/*
Subdomain Routing
*/
if strings.Contains(r.Host, ".") {
//This might be a subdomain. See if there are any subdomain proxy router for this
//Remove the port if any

sep := h.Parent.getSubdomainProxyEndpointFromHostname(domainOnly)
if sep != nil {
if sep.RequireBasicAuth {
err := h.handleBasicAuthRouting(w, r, sep)
if err != nil {
return
}
}
h.subdomainRequest(w, r, sep)
return
}
}

/*
Virtual Directory Routing
*/
//Clean up the request URI
proxyingPath := strings.TrimSpace(r.RequestURI)
targetProxyEndpoint := h.Parent.getTargetProxyEndpointFromRequestURI(proxyingPath)
if targetProxyEndpoint != nil {
if targetProxyEndpoint.RequireBasicAuth {
err := h.handleBasicAuthRouting(w, r, targetProxyEndpoint)
if err != nil {
return
}
}
h.proxyRequest(w, r, targetProxyEndpoint)
} else if !strings.HasSuffix(proxyingPath, "/") {
potentialProxtEndpoint := h.Parent.getTargetProxyEndpointFromRequestURI(proxyingPath + "/")

if potentialProxtEndpoint != nil {
//Missing tailing slash. Redirect to target proxy endpoint
http.Redirect(w, r, r.RequestURI+"/", http.StatusTemporaryRedirect)
//h.proxyRequest(w, r, potentialProxtEndpoint)
} else {
//Passthrough the request to root
h.proxyRequest(w, r, h.Parent.Root)
}
} else {
//No routing rules found. Route to root.
h.proxyRequest(w, r, h.Parent.Root)
}
}
47 changes: 47 additions & 0 deletions src/mod/dynamicproxy/basicAuth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package dynamicproxy

import (
"errors"
"net/http"

"imuslab.com/zoraxy/mod/auth"
)

/*
BasicAuth.go
This file handles the basic auth on proxy endpoints
if RequireBasicAuth is set to true
*/

func (h *ProxyHandler) handleBasicAuthRouting(w http.ResponseWriter, r *http.Request, pe *ProxyEndpoint) error {
proxyType := "vdir-auth"
if pe.ProxyType == ProxyType_Subdomain {
proxyType = "subd-auth"
}
u, p, ok := r.BasicAuth()
if !ok {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
w.WriteHeader(401)
return errors.New("unauthorized")
}

//Check for the credentials to see if there is one matching
hashedPassword := auth.Hash(p)
matchingFound := false
for _, cred := range pe.BasicAuthCredentials {
if u == cred.Username && hashedPassword == cred.PasswordHash {
matchingFound = true
break
}
}

if !matchingFound {
h.logRequest(r, false, 401, proxyType, pe.Domain)
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
w.WriteHeader(401)
return errors.New("unauthorized")
}

return nil
}
12 changes: 7 additions & 5 deletions src/mod/dynamicproxy/dpcore/dpcore.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ type requestCanceler interface {
CancelRequest(req *http.Request)
}

func NewDynamicProxyCore(target *url.URL, prepender string) *ReverseProxy {
func NewDynamicProxyCore(target *url.URL, prepender string, ignoreTLSVerification bool) *ReverseProxy {
targetQuery := target.RawQuery
director := func(req *http.Request) {
req.URL.Scheme = target.Scheme
Expand All @@ -95,7 +95,12 @@ func NewDynamicProxyCore(target *url.URL, prepender string) *ReverseProxy {
thisTransporter.(*http.Transport).MaxIdleConnsPerHost = 3000
thisTransporter.(*http.Transport).IdleConnTimeout = 10 * time.Second
thisTransporter.(*http.Transport).MaxConnsPerHost = 0
thisTransporter.(*http.Transport).DisableCompression = true
//thisTransporter.(*http.Transport).DisableCompression = true

if ignoreTLSVerification {
//Ignore TLS certificate validation error
thisTransporter.(*http.Transport).TLSClientConfig.InsecureSkipVerify = true
}

return &ReverseProxy{
Director: director,
Expand Down Expand Up @@ -278,9 +283,6 @@ func addXForwardedForHeader(req *http.Request) {

func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr *ResponseRewriteRuleSet) error {
transport := p.Transport
if transport == nil {
transport = http.DefaultTransport
}

outreq := new(http.Request)
// Shallow copies of maps, like header
Expand Down
Loading

0 comments on commit 5952a1b

Please sign in to comment.