Browse Source

auto update script executed

Toby Chui 1 year ago
parent
commit
7e79929c1d

+ 9 - 0
mod/dynamicproxy/Server.go

@@ -37,6 +37,15 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	//Check if there are external routing rule matches.
+	//If yes, route them via external rr
+	matchedRoutingRule := h.Parent.GetMatchingRoutingRule(r)
+	if matchedRoutingRule != nil {
+		//Matching routing rule found. Let the sub-router handle it
+		matchedRoutingRule.Route(w, r)
+		return
+	}
+
 	//Extract request host to see if it is virtual directory or subdomain
 	domainOnly := r.Host
 	if strings.Contains(r.Host, ":") {

+ 2 - 0
mod/dynamicproxy/dynamicproxy.go

@@ -43,6 +43,7 @@ type Router struct {
 	mux               http.Handler
 	server            *http.Server
 	tlsListener       net.Listener
+	routingRules      []*RoutingRule
 }
 
 type ProxyEndpoint struct {
@@ -72,6 +73,7 @@ func NewDynamicProxy(option RouterOption) (*Router, error) {
 		SubdomainEndpoint: &domainMap,
 		Running:           false,
 		server:            nil,
+		routingRules:      []*RoutingRule{},
 	}
 
 	thisRouter.mux = &ProxyHandler{

+ 85 - 0
mod/dynamicproxy/special.go

@@ -0,0 +1,85 @@
+package dynamicproxy
+
+import (
+	"errors"
+	"net/http"
+)
+
+/*
+	Special.go
+
+	This script handle special routing rules
+	by external modules
+*/
+
+type RoutingRule struct {
+	ID             string
+	MatchRule      func(r *http.Request) bool
+	RoutingHandler http.Handler
+	Enabled        bool
+}
+
+//Router functions
+//Check if a routing rule exists given its id
+func (router *Router) GetRoutingRuleById(rrid string) (*RoutingRule, error) {
+	for _, rr := range router.routingRules {
+		if rr.ID == rrid {
+			return rr, nil
+		}
+	}
+
+	return nil, errors.New("routing rule with given id not found")
+}
+
+//Add a routing rule to the router
+func (router *Router) AddRoutingRules(rr *RoutingRule) error {
+	_, err := router.GetRoutingRuleById(rr.ID)
+	if err != nil {
+		//routing rule with given id already exists
+		return err
+	}
+
+	router.routingRules = append(router.routingRules, rr)
+	return nil
+}
+
+//Remove a routing rule from the router
+func (router *Router) RemoveRoutingRule(rrid string) {
+	newRoutingRules := []*RoutingRule{}
+	for _, rr := range router.routingRules {
+		if rr.ID != rrid {
+			newRoutingRules = append(newRoutingRules, rr)
+		}
+	}
+
+	router.routingRules = newRoutingRules
+}
+
+//Get all routing rules
+func (router *Router) GetAllRoutingRules() []*RoutingRule {
+	return router.routingRules
+}
+
+//Get the matching routing rule that describe this request.
+//Return nil if no routing rule is match
+func (router *Router) GetMatchingRoutingRule(r *http.Request) *RoutingRule {
+	for _, thisRr := range router.routingRules {
+		if thisRr.IsMatch(r) {
+			return thisRr
+		}
+	}
+	return nil
+}
+
+//Routing Rule functions
+//Check if a request object match the
+func (e *RoutingRule) IsMatch(r *http.Request) bool {
+	if !e.Enabled {
+		return false
+	}
+	return e.MatchRule(r)
+}
+
+func (e *RoutingRule) Route(w http.ResponseWriter, r *http.Request) {
+	e.RoutingHandler.ServeHTTP(w, r)
+}

+ 12 - 0
specialRouter.go

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

+ 111 - 3
web/components/blacklist.html

@@ -315,6 +315,24 @@
 
     </tbody>
   </table>
+  <div class="ui divider"></div>
+  <h4>Visitor IP list</h4>
+  <button style="margin-top: -1em;" onclick="initBlacklistQuickBanTable();" class="ui green small right floated circular basic icon button"><i class="ui refresh icon"></i></button>
+  <p>Observe strange traffic on your sites? Ban them in the list below.</p>
+ 
+  <table class="ui celled table" id="ipTable">
+    <thead>
+      <tr>
+        <th>IP</th>
+        <th>Access Count</th>
+        <th>Blacklist</th>
+      </tr>
+    </thead>
+    <tbody>
+    </tbody>
+  </table>
+  <div class="pagination"></div>
+
 <script>
     $(".dropdown").dropdown();
 
@@ -427,13 +445,15 @@
                         icon = "home icon";
                     }
                     $('#blacklistIpTable').append(`
-                        <tr>
-                        <td><i class="${icon}"></i> ${ip}</td>
-                        <td><button class="ui icon basic mini red button" onclick="removeIpBlacklist('${ip}');"><i class="trash alternate icon"></i></button></td>
+                        <tr class="blacklistItem ${encodeURIComponent(ip.split(".").join("_"))}">
+                            <td><i class="${icon}"></i> ${ip}</td>
+                            <td><button class="ui icon basic mini red button" onclick="removeIpBlacklist('${ip}');"><i class="trash alternate icon"></i></button></td>
                         </tr>
                     `);
                 });
             }
+
+            initBlacklistQuickBanTable();
         });
     }
     initIpBanTable();
@@ -563,6 +583,7 @@
                 error: function() {
                     alert("Failed to remove IP address from blacklist.");
                 }
+                
             });
         }
     }
@@ -594,6 +615,93 @@
     }
     initBlacklistEnableState();
 
+    //Load the summary to ip access table
+    function initBlacklistQuickBanTable(){
+        $.get("/api/stats/summary", function(data){
+            initIpAccessTable(data.RequestClientIp);
+        })
+    }
+    initBlacklistQuickBanTable();
+
+    var blacklist_entriesPerPage = 30;
+    var blacklist_currentPage = 1;
+    var blacklist_totalPages = 0;
+
+    function initIpAccessTable(ipAccessCounts){
+        blacklist_totalPages = Math.ceil(Object.keys(ipAccessCounts).length / blacklist_entriesPerPage);
+
+        function sortkv(obj) {
+            var sortable = [];
+            for (var key in obj) {
+                if (obj.hasOwnProperty(key)) {
+                sortable.push([key, obj[key]]);
+                }
+            }
+            sortable.sort(function(a, b) {
+                return b[1] - a[1];
+            });
+            var sortedObj = {};
+            sortable.forEach(function(item) {
+                sortedObj[item[0]] = item[1];
+            });
+            return sortedObj;
+        }
+
+        ipAccessCounts = sortkv(ipAccessCounts);
 
+        function renderTable() {
+            var tableBody = $("#ipTable tbody");
+            tableBody.empty();
 
+            var startIndex = (blacklist_currentPage - 1) * blacklist_entriesPerPage;
+            var endIndex = startIndex + blacklist_entriesPerPage;
+            var slicedEntries = Object.entries(ipAccessCounts).slice(startIndex, endIndex);
+
+            slicedEntries.forEach(function([ip, accessCount]) {
+                var row = $("<tr>").appendTo(tableBody);
+                $("<td>").text(ip).appendTo(row);
+                $("<td>").text(accessCount).appendTo(row);
+                    if (ipInBlacklist(ip)){
+                        $("<td>").html(`<button class="ui basic green small button" title"Unban IP" onclick="handleUnban('${ip}');"><i class="green check icon"></i> Unban</button>`).appendTo(row);
+                    }else{
+                        $("<td>").html(`<button class="ui basic red small button" title"Ban IP" onclick="handleBanIp('${ip}');"><i class="red ban icon"></i> Ban</button>`).appendTo(row);
+                    }
+                
+            });
+        }
+
+        function renderPagination() {
+            var paginationDiv = $(".pagination");
+            paginationDiv.empty();
+
+            for (var i = 1; i <= blacklist_totalPages; i++) {
+                var button = $("<button>").text(i).addClass("ui small basic compact button");
+                if (i === blacklist_currentPage) {
+                    button.addClass("disabled");
+                }
+                button.click(function() {
+                    blacklist_currentPage = parseInt($(this).text());
+                    renderTable();
+                    renderPagination();
+                });
+                button.appendTo(paginationDiv);
+            }
+        }
+
+        renderTable();
+        renderPagination();
+    }
+
+    function ipInBlacklist(targetIp){
+        return $(".blacklistItem." + encodeURIComponent(targetIp.split(".").join("_"))).length > 0;
+    }
+
+    function handleBanIp(targetIp){
+        $("#ipAddressInput").val(targetIp);
+        addIpBlacklist();
+    }
+
+    function handleUnban(targetIp){
+        removeIpBlacklist(targetIp);
+    }
 </script>

+ 41 - 1
web/components/uptime.html

@@ -1,3 +1,16 @@
+<h3><i class="clock green icon"></i> Uptime Monitor</h3>
+<p>Check the online state of proxied targets</p>
+
+<div class="ui toggle checkbox" id="utmEnable">
+    <input type="checkbox" name="utmEnable">
+    <label>Enable External Access</label>
+</div>
+<div class="ui message">
+    You can expose the uptime monitor interface to public by adding: <br>
+    <code>%uptime_monitor%</code> 
+    <br>as a subdomain or virtual directory target URL in the "Create Proxy Rules" tab.
+</div>
+<div class="ui divider"></div>
 <div id="utmrender" class="ui basic segment">
     <div class="ui basic segment">
         <h4 class="ui header">
@@ -10,12 +23,29 @@
     </div>
 </div>
 <div align="center">
-    <button class="ui basic circular green icon button"><i class="refresh icon"></i></button>   
+    <button class="ui basic circular green icon button" onclick="reloadUptimeList();"><i class="refresh icon"></i></button>   
 </div>
 
 
 
 <script>
+
+        $('#utmEnable').checkbox({
+          onChange: function() {
+            var utmEnable = $('input[name="utmEnable"]').is(":checked");
+            $.post({
+              url: '/api/toggle-utm',
+              data: {utmEnable: utmEnable},
+              success: function(response) {
+                console.log(response);
+              },
+              error: function(error) {
+                console.log(error);
+              }
+            });
+          }
+        });
+
     function initUptimeTable(){
         $.get("/api/utm/list", function(data){
             let records = data;
@@ -24,6 +54,16 @@
     }
     initUptimeTable();
 
+    function reloadUptimeList(){
+        $("#utmrender").html(`<div class="ui segment">
+        <div class="ui active inverted dimmer" style="z-index: 2;">
+            <div class="ui text loader">Loading</div>
+        </div>
+        <br><br><br><br>
+        </div>`);
+        setTimeout(initUptimeTable, 300);
+    }
+
     //For every 5 minutes
     setInterval(function(){
         $.get("/api/utm/list", function(data){