Added uptime monitor and summary struct converter

This commit is contained in:
Toby Chui 2023-04-15 23:29:25 +08:00
parent b5f3234d45
commit 3902a0283b
6 changed files with 172 additions and 153 deletions

View File

@ -1,118 +1,31 @@
# Zoraxy # ReverseProxy
General purpose request (reverse) proxy and forwarding tool for low power devices. Now written in Go! Reverse proxy subservice for ArozOS
### Features
- Simple to use interface with detail in-system instructions
- Reverse Proxy ### Install
- Subdomain Reverse Proxy Git clone this inside the subservice folder of ArozOS, build it and start it up in ArozOS subservice menu.
- Virtual Directory Reverse Proxy You can also use it separately as a really basic reverse proxy server that server website based on domain / virtual directories. You can also add another load balancer in front of multiple reverse proxy server nodes if it is necessary in your case.
- Redirection Rules
- TLS / SSL setup and deploy
- Blacklist by country or IP address (single IP, CIDR or wildcard for beginners :D) ### Build
- (More features work in progress) Requirement: Go 1.16 or above
## Usage
Zoraxy provide basic authentication system for standalone mode. To use it in standalone mode, follow the instruction below for your desired deployment platform.
### Standalone Mode
Standalone mode is the default mode for Zoraxy. This allow single account to manage your reverse proxy server just like a home router. This mode is suitable for new owners for homelab or makers start growing their web services into multiple servers.
#### Linux
```bash
//Download the latest zoraxy binary and web.tar.gz from the Release page
sudo chmod 775 ./zoraxy web.tar.gz
sudo ./zoraxy -port=:8000
``` ```
#### Windows
Download the binary executable and web.tar.gz, put them into the same folder and double click the binary file to start it.
#### Raspberry Pi
The installation method is same as Linux. If you are using Raspberry Pi 4 or newer models, pick the arm64 release. For older version of Pis, use the arm (armv6) version instead.
#### Other ARM SBCs or Android phone with Termux
The installation method is same as Linux. For other ARM SBCs, please refer to your SBC's CPU architecture and pick the one that is suitable for your device.
### External Permission Managment Mode
If you already have a up-stream reverse proxy server in place with permission management, you can use Zoraxy in noauth mode. To enable no-auth mode, start Zoraxy with the following flag
```bash
./zoraxy -noauth=true
```
*Note: For security reaons, you should only enable no-auth if you are running Zoraxy in a trusted environment or with another authentication management proxy in front.*
#### Use with ArozOS
[ArozOS ](https://arozos.com)subservice is a build in permission managed reverse proxy server. To use zoraxy with arozos, connect to your arozos host via ssh and use the following command to install zoraxy
```bash
# cd into your arozos subservice folder. Sometime it is under ~/arozos/src/subservice
cd ~/arozos/subservices cd ~/arozos/subservices
mkdir zoraxy git clone {this_repo}
cd ./zoraxy cd ReverseProxy
./build.sh
# Download the release binary from Github release
wget {binary executable link from release page}
wget {web.tar.gz link from release page}
# Set permission. Change this if required
sudo chmod 775 -R ./
# Start zoraxy to see if the downloaded arch is correct. If yes, you should
# see it start unzipping
./zoraxy
# After the unzip done, press Ctrl + C to kill it
# Rename it to valid arozos subservice binary format
mv ./zoraxy zoraxy_linux_amd64
# If you are using SBCs with different CPU arch
mv ./zoraxy zoraxy_linux_arm
mv ./zoraxy zoraxy_linux_arm64
# Restart arozos
sudo systemctl restart arozos
``` ```
To start the module, go to System Settings > Modules > Subservice and enable it in the menu. You should be able to see a new module named "Zoraxy" pop up in the start menu. To start the module, make sure .disabled file does not exists and start arozos system. You should be able to see a new module named "ReverseProxy" pop up in the start menu.
### Usage
## Build from Source
*Requirement: Go 1.17 or above*
```bash
git clone https://github.com/tobychui/zoraxy
cd ./zoraxy/src
go mod tidy
go build
./zoraxy
```
### Forward Modes
#### Proxy Modes #### Proxy Modes
@ -121,8 +34,12 @@ There are two mode in the ReverseProxy Subservice
1. vdir mode (Virtual Dirctories) 1. vdir mode (Virtual Dirctories)
2. subd mode (Subdomain Proxying Mode) 2. subd mode (Subdomain Proxying Mode)
Vdir mode proxy web request based on the virtual directories given in the request URL. For example, when configured to redirect /example to example.com, any visits to {your_domain}/example will be proxied to example.com. Vdir mode proxy web request based on the virtual directories given in the request URL. For example, when configured to redirect /example to example.com, any visits to {your_domain}/example will be proxied to example.com.
Subd mode proxy web request based on sub-domain exists in the request URL. For example, when configured to redirect example.localhost to example.com, any visits that includes example.localhost (e.g. example.localhost/page1) will be proxied to example.com (e.g. example.com/page1) Subd mode proxy web request based on sub-domain exists in the request URL. For example, when configured to redirect example.localhost to example.com, any visits that includes example.localhost (e.g. example.localhost/page1) will be proxied to example.com (e.g. example.com/page1)
#### Root Proxy #### Root Proxy
@ -131,6 +48,3 @@ Root proxy is the main proxy destination where if all proxy root name did not ma
## License
To be decided (Currently: All Right Reserved)

View File

@ -68,9 +68,10 @@ func initAPIs() {
authRouter.HandleFunc("/api/blacklist/ip/remove", handleIpBlacklistRemove) authRouter.HandleFunc("/api/blacklist/ip/remove", handleIpBlacklistRemove)
authRouter.HandleFunc("/api/blacklist/enable", handleBlacklistEnable) authRouter.HandleFunc("/api/blacklist/enable", handleBlacklistEnable)
//Statistic API //Statistic & uptime monitoring API
authRouter.HandleFunc("/api/stats/summary", statisticCollector.HandleTodayStatLoad) authRouter.HandleFunc("/api/stats/summary", statisticCollector.HandleTodayStatLoad)
authRouter.HandleFunc("/api/stats/countries", HandleCountryDistrSummary)
authRouter.HandleFunc("/api/utm/list", HandleUptimeMonitorListing)
//Upnp //Upnp
authRouter.HandleFunc("/api/upnp/discover", handleUpnpDiscover) authRouter.HandleFunc("/api/upnp/discover", handleUpnpDiscover)
//If you got APIs to add, append them here //If you got APIs to add, append them here

97
src/helpers.go Normal file
View File

@ -0,0 +1,97 @@
package main
import (
"encoding/json"
"net/http"
"imuslab.com/zoraxy/mod/dynamicproxy"
"imuslab.com/zoraxy/mod/uptime"
"imuslab.com/zoraxy/mod/utils"
)
/*
Statistic Summary
*/
//Handle conversion of statistic daily summary to country summary
func HandleCountryDistrSummary(w http.ResponseWriter, r *http.Request) {
requestClientCountry := map[string]int{}
statisticCollector.DailySummary.RequestClientIp.Range(func(key, value interface{}) bool {
//Get this client country of original
clientIp := key.(string)
//requestCount := value.(int)
ci, err := geodbStore.ResolveCountryCodeFromIP(clientIp)
if err != nil {
return true
}
isoCode := ci.CountryIsoCode
if isoCode == "" {
//local or reserved addr
isoCode = "local"
}
uc, ok := requestClientCountry[isoCode]
if !ok {
//Create the counter
requestClientCountry[isoCode] = 1
} else {
requestClientCountry[isoCode] = uc + 1
}
return true
})
js, _ := json.Marshal(requestClientCountry)
utils.SendJSONResponse(w, string(js))
}
/*
Up Time Monitor
*/
//Generate uptime monitor targets from reverse proxy rules
func GetUptimeTargetsFromReverseProxyRules(dp *dynamicproxy.Router) []*uptime.Target {
subds := dp.GetSDProxyEndpointsAsMap()
vdirs := dp.GetVDProxyEndpointsAsMap()
UptimeTargets := []*uptime.Target{}
for subd, target := range subds {
url := "http://" + target.Domain
protocol := "http"
if target.RequireTLS {
url = "https://" + target.Domain
protocol = "https"
}
UptimeTargets = append(UptimeTargets, &uptime.Target{
ID: subd,
Name: subd,
URL: url,
Protocol: protocol,
})
}
for vdir, target := range vdirs {
url := "http://" + target.Domain
protocol := "http"
if target.RequireTLS {
url = "https://" + target.Domain
protocol = "https"
}
UptimeTargets = append(UptimeTargets, &uptime.Target{
ID: vdir,
Name: "*" + vdir,
URL: url,
Protocol: protocol,
})
}
return UptimeTargets
}
//Handle rendering up time monitor data
func HandleUptimeMonitorListing(w http.ResponseWriter, r *http.Request) {
if uptimeMonitor != nil {
uptimeMonitor.HandleUptimeLogRead(w, r)
} else {
http.Error(w, "500 - Internal Server Error", http.StatusInternalServerError)
return
}
}

View File

@ -1,14 +1,12 @@
package main package main
import ( import (
"errors"
"flag" "flag"
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"os" "os"
"os/signal" "os/signal"
"path/filepath"
"syscall" "syscall"
"time" "time"
@ -20,7 +18,7 @@ import (
"imuslab.com/zoraxy/mod/statistic" "imuslab.com/zoraxy/mod/statistic"
"imuslab.com/zoraxy/mod/tlscert" "imuslab.com/zoraxy/mod/tlscert"
"imuslab.com/zoraxy/mod/upnp" "imuslab.com/zoraxy/mod/upnp"
"imuslab.com/zoraxy/mod/utils" "imuslab.com/zoraxy/mod/uptime"
) )
//General flags //General flags
@ -29,16 +27,17 @@ var showver = flag.Bool("version", false, "Show version of this server")
var ( var (
name = "Zoraxy" name = "Zoraxy"
version = "2.1" version = "2.11"
handler *aroz.ArozHandler handler *aroz.ArozHandler //Handle arozos managed permission system
sysdb *database.Database sysdb *database.Database //System database
authAgent *auth.AuthAgent authAgent *auth.AuthAgent //Authentication agent
tlsCertManager *tlscert.Manager tlsCertManager *tlscert.Manager //TLS / SSL management
redirectTable *redirection.RuleTable redirectTable *redirection.RuleTable //Handle special redirection rule sets
geodbStore *geodb.Store geodbStore *geodb.Store //GeoIP database
statisticCollector *statistic.Collector statisticCollector *statistic.Collector //Collecting statistic from visitors
upnpClient *upnp.UPnPClient upnpClient *upnp.UPnPClient //UPnP Client for poking holes
uptimeMonitor *uptime.Monitor //Uptime monitor service worker
) )
// Kill signal handler. Do something before the system the core terminate. // Kill signal handler. Do something before the system the core terminate.
@ -63,11 +62,11 @@ func main() {
Name: name, Name: name,
Desc: "Dynamic Reverse Proxy Server", Desc: "Dynamic Reverse Proxy Server",
Group: "Network", Group: "Network",
IconPath: "Zoraxy/img/small_icon.png", IconPath: "reverseproxy/img/small_icon.png",
Version: version, Version: version,
StartDir: "Zoraxy/index.html", StartDir: "reverseproxy/index.html",
SupportFW: true, SupportFW: true,
LaunchFWDir: "Zoraxy/index.html", LaunchFWDir: "reverseproxy/index.html",
SupportEmb: false, SupportEmb: false,
InitFWSize: []int{1080, 580}, InitFWSize: []int{1080, 580},
}) })
@ -79,9 +78,6 @@ func main() {
SetupCloseHandler() SetupCloseHandler()
//Check if all required files are here
ValidateSystemFiles()
//Create database //Create database
db, err := database.NewDatabase("sys.db", false) db, err := database.NewDatabase("sys.db", false)
if err != nil { if err != nil {
@ -127,6 +123,10 @@ func main() {
panic(err) panic(err)
} }
if err != nil {
panic(err)
}
//Create a upnp client //Create a upnp client
err = initUpnp() err = initUpnp()
if err != nil { if err != nil {
@ -151,34 +151,3 @@ func main() {
} }
} }
//Unzip web.tar.gz if file exists
func ValidateSystemFiles() error {
if !utils.FileExists("./web") || !utils.FileExists("./system") {
//Check if the web.tar.gz exists
if utils.FileExists("./web.tar.gz") {
//Unzip the file
f, err := os.Open("./web.tar.gz")
if err != nil {
return err
}
err = utils.ExtractTarGzipByStream(filepath.Clean("./"), f, true)
if err != nil {
return err
}
err = f.Close()
if err != nil {
return err
}
//Delete the web.tar.gz
os.Remove("./web.tar.gz")
} else {
return errors.New("system files not found")
}
}
return errors.New("system files not found or corrupted")
}

View File

@ -11,6 +11,7 @@ import (
"time" "time"
"imuslab.com/zoraxy/mod/dynamicproxy" "imuslab.com/zoraxy/mod/dynamicproxy"
"imuslab.com/zoraxy/mod/uptime"
"imuslab.com/zoraxy/mod/utils" "imuslab.com/zoraxy/mod/utils"
) )
@ -95,6 +96,18 @@ func ReverseProxtInit() {
dynamicProxyRouter.StartProxyService() dynamicProxyRouter.StartProxyService()
log.Println("Dynamic Reverse Proxy service started") log.Println("Dynamic Reverse Proxy service started")
//Add all proxy services to uptime monitor
//Create a uptime monitor service
go func() {
//This must be done in go routine to prevent blocking on system startup
uptimeMonitor, _ = uptime.NewUptimeMonitor(&uptime.Config{
Targets: GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter),
Interval: 300, //5 minutes
MaxRecordsStore: 288, //1 day
})
log.Println("Uptime Monitor background service started")
}()
} }
func ReverseProxyHandleOnOff(w http.ResponseWriter, r *http.Request) { func ReverseProxyHandleOnOff(w http.ResponseWriter, r *http.Request) {
@ -178,6 +191,12 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
//Save it //Save it
SaveReverseProxyConfig(eptype, rootname, endpoint, useTLS) SaveReverseProxyConfig(eptype, rootname, endpoint, useTLS)
//Update utm if exists
if uptimeMonitor != nil {
uptimeMonitor.Config.Targets = GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter)
uptimeMonitor.CleanRecords()
}
utils.SendOK(w) utils.SendOK(w)
} }
@ -199,6 +218,13 @@ func DeleteProxyEndpoint(w http.ResponseWriter, r *http.Request) {
} }
RemoveReverseProxyConfig(ep) RemoveReverseProxyConfig(ep)
//Update utm if exists
if uptimeMonitor != nil {
uptimeMonitor.Config.Targets = GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter)
uptimeMonitor.CleanRecords()
}
utils.SendOK(w) utils.SendOK(w)
} }

12
src/specialRouter.go Normal file
View File

@ -0,0 +1,12 @@
package main
/*
specialRouter.go
This script holds special routers
that handle special features in sub modules
*/
func injectSpecialRoutingRules() {
}