Kaynağa Gözat

Optimized codebase for stream proxy and config file storage

Toby Chui 4 ay önce
ebeveyn
işleme
7b3f5f443a

+ 1 - 1
mod/email/email.go

@@ -16,7 +16,7 @@ type Sender struct {
 	Port       int    //E.g. 587
 	Username   string //Username of the email account
 	Password   string //Password of the email account
-	SenderAddr string //e.g. admin@arozos.com
+	SenderAddr string //e.g. admin@aroz.org
 }
 
 // Create a new email sender object

+ 71 - 17
mod/streamproxy/streamproxy.go

@@ -1,15 +1,18 @@
 package streamproxy
 
 import (
+	"encoding/json"
 	"errors"
-	"log"
 	"net"
+	"os"
+	"path/filepath"
 	"sync"
 	"sync/atomic"
 	"time"
 
 	"github.com/google/uuid"
-	"imuslab.com/zoraxy/mod/database"
+	"imuslab.com/zoraxy/mod/info/logger"
+	"imuslab.com/zoraxy/mod/utils"
 )
 
 /*
@@ -48,9 +51,10 @@ type ProxyRelayConfig struct {
 }
 
 type Options struct {
-	Database             *database.Database
 	DefaultTimeout       int
 	AccessControlHandler func(net.Conn) bool
+	ConfigStore          string         //Folder to store the config files, will be created if not exists
+	Logger               *logger.Logger //Logger for the stream proxy
 }
 
 type Manager struct {
@@ -63,13 +67,37 @@ type Manager struct {
 
 }
 
-func NewStreamProxy(options *Options) *Manager {
-	options.Database.NewTable("tcprox")
+func NewStreamProxy(options *Options) (*Manager, error) {
+	if !utils.FileExists(options.ConfigStore) {
+		err := os.MkdirAll(options.ConfigStore, 0775)
+		if err != nil {
+			return nil, err
+		}
+	}
 
 	//Load relay configs from db
 	previousRules := []*ProxyRelayConfig{}
-	if options.Database.KeyExists("tcprox", "rules") {
-		options.Database.Read("tcprox", "rules", &previousRules)
+	streamProxyConfigFiles, err := filepath.Glob(options.ConfigStore + "/*.config")
+	if err != nil {
+		return nil, err
+	}
+
+	for _, configFile := range streamProxyConfigFiles {
+		//Read file into bytes
+		configBytes, err := os.ReadFile(configFile)
+		if err != nil {
+			options.Logger.PrintAndLog("stream-prox", "Read stream proxy config failed", err)
+			continue
+		}
+		thisRelayConfig := &ProxyRelayConfig{}
+		err = json.Unmarshal(configBytes, thisRelayConfig)
+		if err != nil {
+			options.Logger.PrintAndLog("stream-prox", "Unmarshal stream proxy config failed", err)
+			continue
+		}
+
+		//Append the config to the list
+		previousRules = append(previousRules, thisRelayConfig)
 	}
 
 	//Check if the AccessControlHandler is empty. If yes, set it to always allow access
@@ -91,14 +119,27 @@ func NewStreamProxy(options *Options) *Manager {
 		rule.parent = &thisManager
 		if rule.Running {
 			//This was previously running. Start it again
-			log.Println("[Stream Proxy] Resuming stream proxy rule " + rule.Name)
+			thisManager.logf("Resuming stream proxy rule "+rule.Name, nil)
 			rule.Start()
 		}
 	}
 
 	thisManager.Configs = previousRules
 
-	return &thisManager
+	return &thisManager, nil
+}
+
+// Wrapper function to log error
+func (m *Manager) logf(message string, originalError error) {
+	if m.Options.Logger == nil {
+		//Print to fmt
+		if originalError != nil {
+			message += ": " + originalError.Error()
+		}
+		println(message)
+		return
+	}
+	m.Options.Logger.PrintAndLog("stream-prox", message, originalError)
 }
 
 func (m *Manager) NewConfig(config *ProxyRelayOptions) string {
@@ -190,8 +231,19 @@ func (m *Manager) RemoveConfig(configUUID string) error {
 	return errors.New("config not found")
 }
 
+// Save all configs to ConfigStore folder
 func (m *Manager) SaveConfigToDatabase() {
-	m.Options.Database.Write("tcprox", "rules", m.Configs)
+	for _, config := range m.Configs {
+		configBytes, err := json.Marshal(config)
+		if err != nil {
+			m.logf("Failed to marshal stream proxy config", err)
+			continue
+		}
+		err = os.WriteFile(m.Options.ConfigStore+"/"+config.UUID+".config", configBytes, 0775)
+		if err != nil {
+			m.logf("Failed to save stream proxy config", err)
+		}
+	}
 }
 
 /*
@@ -217,9 +269,10 @@ func (c *ProxyRelayConfig) Start() error {
 			if err != nil {
 				if !c.UseTCP {
 					c.Running = false
+					c.udpStopChan = nil
 					c.parent.SaveConfigToDatabase()
 				}
-				log.Println("[TCP] Error starting stream proxy " + c.Name + "(" + c.UUID + "): " + err.Error())
+				c.parent.logf("[proto:udp] Error starting stream proxy "+c.Name+"("+c.UUID+")", err)
 			}
 		}()
 	}
@@ -231,8 +284,9 @@ func (c *ProxyRelayConfig) Start() error {
 			err := c.Port2host(c.ListeningAddress, c.ProxyTargetAddr, tcpStopChan)
 			if err != nil {
 				c.Running = false
+				c.tcpStopChan = nil
 				c.parent.SaveConfigToDatabase()
-				log.Println("[TCP] Error starting stream proxy " + c.Name + "(" + c.UUID + "): " + err.Error())
+				c.parent.logf("[proto:tcp] Error starting stream proxy "+c.Name+"("+c.UUID+")", err)
 			}
 		}()
 	}
@@ -253,27 +307,27 @@ func (c *ProxyRelayConfig) Restart() {
 	if c.IsRunning() {
 		c.Stop()
 	}
-	time.Sleep(300 * time.Millisecond)
+	time.Sleep(3000 * time.Millisecond)
 	c.Start()
 }
 
 // Stop a running proxy if running
 func (c *ProxyRelayConfig) Stop() {
-	log.Println("[STREAM PROXY] Stopping Stream Proxy " + c.Name)
+	c.parent.logf("Stopping Stream Proxy "+c.Name, nil)
 
 	if c.udpStopChan != nil {
-		log.Println("[STREAM PROXY] Stopping UDP for " + c.Name)
+		c.parent.logf("Stopping UDP for "+c.Name, nil)
 		c.udpStopChan <- true
 		c.udpStopChan = nil
 	}
 
 	if c.tcpStopChan != nil {
-		log.Println("[STREAM PROXY] Stopping TCP for " + c.Name)
+		c.parent.logf("Stopping TCP for "+c.Name, nil)
 		c.tcpStopChan <- true
 		c.tcpStopChan = nil
 	}
 
-	log.Println("[STREAM PROXY] Stopped Stream Proxy " + c.Name)
+	c.parent.logf("Stopped Stream Proxy "+c.Name, nil)
 	c.Running = false
 
 	//Update the running status

+ 60 - 60
mod/webserv/templates/index.html

@@ -1,61 +1,61 @@
-<html>
-    <head>
-        <title>Hello Zoraxy</title>
-        <style>
-            body {
-                font-family: Tahoma, sans-serif;
-                background-color: #f6f6f6;
-                color: #2d2e30;
-            }
-            .sectionHeader{
-                background-color: #c4d0d9;
-                padding: 0.1em;
-            }
-
-            .sectionHeader h3{
-                text-align: center;
-            }
-            .container{
-                margin: 4em;
-                margin-left: 10em;
-                margin-right: 10em;
-                background-color: #fefefe;
-            }
-
-            @media (max-width:960px) {
-                .container{
-                    margin-left: 1em;
-                    margin-right: 1em;
-                }
-
-                .sectionHeader{
-                    padding-left: 1em;
-                    padding-right: 1em;
-                }
-            }
-
-            .textcontainer{
-                padding: 1em;
-            }
-        </style>
-    </head>
-    <body>
-        <div class="container">
-            <div class="sectionHeader">
-                <h3>Welcome to Zoraxy Static Web Server!</h3>
-            </div>
-            <div class="textcontainer">
-                <p>If you see this page, that means your static web server is running.<br> 
-                    By default, all the html files are stored under <code>./web/html/</code> 
-                    relative to the zoraxy runtime directory.<br>
-                    You can upload your html files to your web directory via the <b>Web Directory Manager</b>.
-                </p>
-                <p>
-                    For online documentation, please refer to <a href="//zoraxy.arozos.com">zoraxy.arozos.com</a> or the <a href="https://github.com/tobychui/zoraxy/wiki">project wiki</a>.<br>
-                    Thank you for using Zoraxy!
-                </p>
-            </div>
-           
-        </div>
-    </body>
+<html>
+    <head>
+        <title>Hello Zoraxy</title>
+        <style>
+            body {
+                font-family: Tahoma, sans-serif;
+                background-color: #f6f6f6;
+                color: #2d2e30;
+            }
+            .sectionHeader{
+                background-color: #c4d0d9;
+                padding: 0.1em;
+            }
+
+            .sectionHeader h3{
+                text-align: center;
+            }
+            .container{
+                margin: 4em;
+                margin-left: 10em;
+                margin-right: 10em;
+                background-color: #fefefe;
+            }
+
+            @media (max-width:960px) {
+                .container{
+                    margin-left: 1em;
+                    margin-right: 1em;
+                }
+
+                .sectionHeader{
+                    padding-left: 1em;
+                    padding-right: 1em;
+                }
+            }
+
+            .textcontainer{
+                padding: 1em;
+            }
+        </style>
+    </head>
+    <body>
+        <div class="container">
+            <div class="sectionHeader">
+                <h3>Welcome to Zoraxy Static Web Server!</h3>
+            </div>
+            <div class="textcontainer">
+                <p>If you see this page, that means your static web server is running.<br> 
+                    By default, all the html files are stored under <code>./web/html/</code> 
+                    relative to the zoraxy runtime directory.<br>
+                    You can upload your html files to your web directory via the <b>Web Directory Manager</b>.
+                </p>
+                <p>
+                    For online documentation, please refer to <a href="//zoraxy.aroz.org">zoraxy.aroz.org</a> or the <a href="https://github.com/tobychui/zoraxy/wiki">project wiki</a>.<br>
+                    Thank you for using Zoraxy!
+                </p>
+            </div>
+           
+        </div>
+    </body>
 </html>

+ 7 - 3
start.go

@@ -205,7 +205,7 @@ func startupSequence() {
 		mdnsScanner, err = mdns.NewMDNS(mdns.NetworkHost{
 			HostName:     hostName,
 			Port:         portInt,
-			Domain:       "zoraxy.arozos.com",
+			Domain:       "zoraxy.aroz.org",
 			Model:        "Network Gateway",
 			UUID:         nodeUUID,
 			Vendor:       "imuslab.com",
@@ -262,10 +262,14 @@ func startupSequence() {
 	webSshManager = sshprox.NewSSHProxyManager()
 
 	//Create TCP Proxy Manager
-	streamProxyManager = streamproxy.NewStreamProxy(&streamproxy.Options{
-		Database:             sysdb,
+	streamProxyManager, err = streamproxy.NewStreamProxy(&streamproxy.Options{
 		AccessControlHandler: accessController.DefaultAccessRule.AllowConnectionAccess,
+		ConfigStore:          "./conf/streamproxy",
+		Logger:               SystemWideLogger,
 	})
+	if err != nil {
+		panic(err)
+	}
 
 	//Create WoL MAC storage table
 	sysdb.NewTable("wolmac")

+ 5 - 5
web/components/rules.html

@@ -165,18 +165,18 @@
             <div class="ui basic segment rulesInstructions">
                 <span style="font-size: 1.2em; font-weight: 300;"><i class="ui yellow star icon"></i> Domain</span><br>
                 Example of domain matching keyword:<br>
-                <code>arozos.com</code> <br>Any acess requesting arozos.com will be proxy to the IP address below<br>
+                <code>aroz.org</code> <br>Any acess requesting aroz.org will be proxy to the IP address below<br>
                 <div class="ui divider"></div>
                 <span style="font-size: 1.2em; font-weight: 300;"><i class="ui yellow star icon"></i> Subdomain</span><br>
                 Example of subdomain matching keyword:<br>
-                <code>s1.arozos.com</code> <br>Any request starting with s1.arozos.com will be proxy to the IP address below<br>
+                <code>s1.aroz.org</code> <br>Any request starting with s1.aroz.org will be proxy to the IP address below<br>
                 <div class="ui divider"></div>
                 <span style="font-size: 1.2em; font-weight: 300;"><i class="ui yellow star icon"></i> Wildcard</span><br>
                 Example of wildcard matching keyword:<br>
-                <code>*.arozos.com</code> <br>Any request with a host name matching *.arozos.com will be proxy to the IP address below. Here are some examples.<br>
+                <code>*.aroz.org</code> <br>Any request with a host name matching *.aroz.org will be proxy to the IP address below. Here are some examples.<br>
                 <div class="ui list">
-                    <div class="item"><code>www.arozos.com</code></div>
-                    <div class="item"><code>foo.bar.arozos.com</code></div>
+                    <div class="item"><code>www.aroz.org</code></div>
+                    <div class="item"><code>foo.bar.aroz.org</code></div>
                 </div>
                 <br>
             </div>

+ 12 - 3
web/components/streamprox.html

@@ -74,7 +74,7 @@
                 </div>
             </div>
             <button id="addStreamProxyButton" class="ui basic button" type="submit"><i class="ui green add icon"></i> Create</button>  
-            <button id="editStreamProxyButton" class="ui basic button" onclick="confirmEditTCPProxyConfig(event);" style="display:none;"><i class="ui green check icon"></i> Update</button>  
+            <button id="editStreamProxyButton" class="ui basic button" onclick="confirmEditTCPProxyConfig(event, this);" style="display:none;"><i class="ui green check icon"></i> Update</button>  
             <button class="ui basic red button" onclick="event.preventDefault(); cancelStreamProxyEdit(event);"><i class="ui red remove icon"></i> Cancel</button>  
         </form>
     </div>
@@ -88,7 +88,7 @@
 
             //Check if update mode
             if ($("#editStreamProxyButton").is(":visible")){
-                confirmEditTCPProxyConfig(event);
+                confirmEditTCPProxyConfig(event,$("#editStreamProxyButton")[0]);
                 return;
             }
 
@@ -274,13 +274,18 @@
             }
         }
 
-        function confirmEditTCPProxyConfig(event){
+        function confirmEditTCPProxyConfig(event, btn){
             event.preventDefault();
             event.stopImmediatePropagation();
             var form = $("#streamProxyForm");
+            let originalButtonHTML = $(btn).html();
+            $(btn).html(`<i class="ui loading spinner icon"></i> Updating`);
+            $(btn).addClass("disabled");
 
             var formValid = validateTCPProxyConfig(form);
             if (!formValid){
+                $(btn).html(originalButtonHTML);
+                $(btn).removeClass("disabled");
                 return;
             }
 
@@ -299,6 +304,8 @@
                     timeout: parseInt($("#streamProxyForm input[name=timeout]").val().trim()),
                 },
                 success: function(response) {
+                    $(btn).html(originalButtonHTML);
+                    $(btn).removeClass("disabled");
                     if (response.error) {
                         msgbox(response.error, false, 6000);
                     }else{
@@ -310,6 +317,8 @@
                     
                 },
                 error: function() {
+                    $(btn).html(originalButtonHTML);
+                    $(btn).removeClass("disabled");
                     msgbox('An error occurred while processing the request', false);
                 }
             });

+ 1 - 1
web/components/utils.html

@@ -46,7 +46,7 @@
             <form id="email-form" class="ui form">
                 <div class="field">
                     <label>Sender Address</label>
-                    <input type="text" name="senderAddr" placeholder="E.g. [email protected]os.com">
+                    <input type="text" name="senderAddr" placeholder="E.g. [email protected].org">
                 </div>
                 <div class="field">
                     <p><i class="caret down icon"></i> Connection setup for email service provider</p>

+ 1 - 1
web/index.html

@@ -160,7 +160,7 @@
         <br><br>
         <div class="ui divider"></div>
         <div class="ui container" style="color: grey; font-size: 90%">
-            <p><a href="https://zoraxy.arozos.com" target="_blank">Zoraxy</a> <span class="zrversion"></span> © 2021 - <span class="year"></span> tobychui. Licensed under AGPL</p>
+            <p><a href="https://zoraxy.aroz.org" target="_blank">Zoraxy</a> <span class="zrversion"></span> © 2021 - <span class="year"></span> tobychui. Licensed under AGPL</p>
         </div>
         
         <div id="messageBox" class="ui green floating big compact message">

+ 1 - 1
web/login.html

@@ -175,7 +175,7 @@
             </svg>
         </div>
         <div class="wavebase">
-            <p>Proudly powered by <a href="https://zoraxy.arozos.com" target="_blank">Zoraxy</a></p>
+            <p>Proudly powered by <a href="https://zoraxy.aroz.org" target="_blank">Zoraxy</a></p>
         </div>
     <script>
         AOS.init();

+ 1 - 1
web/reset.html

@@ -201,7 +201,7 @@
             </svg>
         </div>
         <div class="wavebase">
-            <p>Proudly powered by <a href="https://zoraxy.arozos.com" target="_blank">Zoraxy</a></p>
+            <p>Proudly powered by <a href="https://zoraxy.aroz.org" target="_blank">Zoraxy</a></p>
         </div>
     <script>
         AOS.init();

+ 1 - 1
www/templates/blacklist.html

@@ -127,7 +127,7 @@ gtag("event","share",{method:"twitter",event_action:"tweet",content_id:targetUrl
         <span class="cf-footer-separator">•</span>
         <span id="footer" class="cf-footer-item"><span data-translate="your_ip">Your IP</span>: <span class="clientip"></span></span>
         <span class="cf-footer-separator">•</span>
-        <span class="cf-footer-item"><span data-translate="performance_security_by">Performance &amp; security by</span> <a data-orig-proto="https"  href="https://zoraxy.arozos.com" target="_blank">Zoraxy</a></span>
+        <span class="cf-footer-item"><span data-translate="performance_security_by">Performance &amp; security by</span> <a data-orig-proto="https"  href="https://zoraxy.aroz.org" target="_blank">Zoraxy</a></span>
         
       </p>
     </div><!-- /.error-footer -->

+ 1 - 1
www/templates/whitelist.html

@@ -127,7 +127,7 @@ gtag("event","share",{method:"twitter",event_action:"tweet",content_id:targetUrl
         <span class="cf-footer-separator">•</span>
         <span id="footer" class="cf-footer-item"><span data-translate="your_ip">Your IP</span>: <span class="clientip"></span></span>
         <span class="cf-footer-separator">•</span>
-        <span class="cf-footer-item"><span data-translate="performance_security_by">Performance &amp; security by</span> <a data-orig-proto="https" href="https://zoraxy.arozos.com" target="_blank">Zoraxy</a></span>
+        <span class="cf-footer-item"><span data-translate="performance_security_by">Performance &amp; security by</span> <a data-orig-proto="https" href="https://zoraxy.aroz.org" target="_blank">Zoraxy</a></span>
         
       </p>
     </div><!-- /.error-footer -->