Ver Fonte

auto update script executed

Toby Chui há 1 ano atrás
pai
commit
083f7f2072

+ 2 - 2
mod/dynamicproxy/Server.go

@@ -26,14 +26,14 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		} else {
 			w.Write(template)
 		}
-		h.logRequest(r, false, 403, "blacklist")
+		h.logRequest(r, false, 403, "blacklist", "")
 		return
 	}
 
 	//Check if this is a redirection url
 	if h.Parent.Option.RedirectRuleTable.IsRedirectable(r) {
 		statusCode := h.Parent.Option.RedirectRuleTable.HandleRedirect(w, r)
-		h.logRequest(r, statusCode != 500, statusCode, "redirect")
+		h.logRequest(r, statusCode != 500, statusCode, "redirect", "")
 		return
 	}
 

+ 10 - 15
mod/dynamicproxy/proxyRequestHandler.go

@@ -22,12 +22,6 @@ func (router *Router) getTargetProxyEndpointFromRequestURI(requestURI string) *P
 			thisProxyEndpoint := value.(*ProxyEndpoint)
 			targetProxyEndpoint = thisProxyEndpoint
 		}
-		/*
-			if len(requestURI) >= len(rootname) && requestURI[:len(rootname)] == rootname {
-				thisProxyEndpoint := value.(*ProxyEndpoint)
-				targetProxyEndpoint = thisProxyEndpoint
-			}
-		*/
 		return true
 	})
 
@@ -69,7 +63,7 @@ func (h *ProxyHandler) subdomainRequest(w http.ResponseWriter, r *http.Request,
 		if target.RequireTLS {
 			u, _ = url.Parse("wss://" + wsRedirectionEndpoint + requestURL)
 		}
-		h.logRequest(r, true, 101, "subdomain-websocket")
+		h.logRequest(r, true, 101, "subdomain-websocket", target.Domain)
 		wspHandler := websocketproxy.NewProxy(u)
 		wspHandler.ServeHTTP(w, r)
 		return
@@ -82,15 +76,15 @@ func (h *ProxyHandler) subdomainRequest(w http.ResponseWriter, r *http.Request,
 		if errors.As(err, &dnsError) {
 			http.ServeFile(w, r, "./web/hosterror.html")
 			log.Println(err.Error())
-			h.logRequest(r, false, 404, "subdomain-http")
+			h.logRequest(r, false, 404, "subdomain-http", target.Domain)
 		} else {
 			http.ServeFile(w, r, "./web/rperror.html")
 			log.Println(err.Error())
-			h.logRequest(r, false, 521, "subdomain-http")
+			h.logRequest(r, false, 521, "subdomain-http", target.Domain)
 		}
 	}
 
-	h.logRequest(r, true, 200, "subdomain-http")
+	h.logRequest(r, true, 200, "subdomain-http", target.Domain)
 }
 
 func (h *ProxyHandler) proxyRequest(w http.ResponseWriter, r *http.Request, target *ProxyEndpoint) {
@@ -109,7 +103,7 @@ func (h *ProxyHandler) proxyRequest(w http.ResponseWriter, r *http.Request, targ
 		if target.RequireTLS {
 			u, _ = url.Parse("wss://" + wsRedirectionEndpoint + r.URL.String())
 		}
-		h.logRequest(r, true, 101, "vdir-websocket")
+		h.logRequest(r, true, 101, "vdir-websocket", target.Domain)
 		wspHandler := websocketproxy.NewProxy(u)
 		wspHandler.ServeHTTP(w, r)
 		return
@@ -129,18 +123,18 @@ func (h *ProxyHandler) proxyRequest(w http.ResponseWriter, r *http.Request, targ
 		if errors.As(err, &dnsError) {
 			http.ServeFile(w, r, "./web/hosterror.html")
 			log.Println(err.Error())
-			h.logRequest(r, false, 404, "vdir-http")
+			h.logRequest(r, false, 404, "vdir-http", target.Domain)
 		} else {
 			http.ServeFile(w, r, "./web/rperror.html")
 			log.Println(err.Error())
-			h.logRequest(r, false, 521, "vdir-http")
+			h.logRequest(r, false, 521, "vdir-http", target.Domain)
 		}
 	}
-	h.logRequest(r, true, 200, "vdir-http")
+	h.logRequest(r, true, 200, "vdir-http", target.Domain)
 
 }
 
-func (h *ProxyHandler) logRequest(r *http.Request, succ bool, statusCode int, forwardType string) {
+func (h *ProxyHandler) logRequest(r *http.Request, succ bool, statusCode int, forwardType string, target string) {
 	if h.Parent.Option.StatisticCollector != nil {
 		go func() {
 			requestInfo := statistic.RequestInfo{
@@ -152,6 +146,7 @@ func (h *ProxyHandler) logRequest(r *http.Request, succ bool, statusCode int, fo
 				Referer:                       r.Referer(),
 				UserAgent:                     r.UserAgent(),
 				RequestURL:                    r.Host + r.RequestURI,
+				Target:                        target,
 			}
 			h.Parent.Option.StatisticCollector.RecordRequest(requestInfo)
 		}()

+ 1 - 28
mod/statistic/handler.go

@@ -32,35 +32,8 @@ func (c *Collector) HandleTodayStatLoad(w http.ResponseWriter, r *http.Request)
 		utils.SendJSONResponse(w, string(js))
 	} else {
 		//Return everything
-		exported := DailySummaryExport{
-			TotalRequest:    d.TotalRequest,
-			ErrorRequest:    d.ErrorRequest,
-			ValidRequest:    d.ValidRequest,
-			ForwardTypes:    make(map[string]int),
-			RequestOrigin:   make(map[string]int),
-			RequestClientIp: make(map[string]int),
-		}
-
-		// Export ForwardTypes sync.Map
-		d.ForwardTypes.Range(func(key, value interface{}) bool {
-			exported.ForwardTypes[key.(string)] = value.(int)
-			return true
-		})
-
-		// Export RequestOrigin sync.Map
-		d.RequestOrigin.Range(func(key, value interface{}) bool {
-			exported.RequestOrigin[key.(string)] = value.(int)
-			return true
-		})
-
-		// Export RequestClientIp sync.Map
-		d.RequestClientIp.Range(func(key, value interface{}) bool {
-			exported.RequestClientIp[key.(string)] = value.(int)
-			return true
-		})
-
+		exported := c.GetExportSummary()
 		js, _ := json.Marshal(exported)
-
 		utils.SendJSONResponse(w, string(js))
 	}
 

+ 1 - 0
mod/statistic/statistic.go

@@ -40,6 +40,7 @@ type RequestInfo struct {
 	Referer                       string
 	UserAgent                     string
 	RequestURL                    string
+	Target                        string
 }
 
 type CollectorOption struct {

+ 6 - 0
mod/statistic/structconv.go

@@ -100,3 +100,9 @@ func DailySummaryExportToSummary(export DailySummaryExport) DailySummary {
 
 	return summary
 }
+
+// External object function call
+func (c *Collector) GetExportSummary() *DailySummaryExport {
+	exportFormatDailySummary := DailySummaryToExport(*c.DailySummary)
+	return &exportFormatDailySummary
+}

+ 14 - 0
mod/tcpprox/handler.go

@@ -0,0 +1,14 @@
+package tcpprox
+
+import "net/http"
+
+/*
+	Handler.go
+	Handlers for the tcprox. Remove this file
+	if your application do not need any http
+	handler.
+*/
+
+func HandleListProxyConfigs(w http.ResponseWriter, r *http.Request) {
+
+}

+ 289 - 0
mod/tcpprox/nb.go

@@ -0,0 +1,289 @@
+package main
+
+import (
+	"fmt"
+	"io"
+	"log"
+	"net"
+	"os"
+	"regexp"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+const timeout = 5
+
+func main() {
+	//log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
+	log.SetFlags(log.Ldate | log.Lmicroseconds)
+
+	printWelcome()
+
+	args := os.Args
+	argc := len(os.Args)
+	if argc <= 2 {
+		printHelp()
+		os.Exit(0)
+	}
+
+	//TODO:support UDP protocol
+
+	/*var logFileError error
+	if argc > 5 && args[4] == "-log" {
+		logPath := args[5] + "/" + time.Now().Format("2006_01_02_15_04_05") // "2006-01-02 15:04:05"
+		logPath += args[1] + "-" + strings.Replace(args[2], ":", "_", -1) + "-" + args[3] + ".log"
+		logPath = strings.Replace(logPath, `\`, "/", -1)
+		logPath = strings.Replace(logPath, "//", "/", -1)
+		logFile, logFileError = os.OpenFile(logPath, os.O_APPEND|os.O_CREATE, 0666)
+		if logFileError != nil {
+			log.Fatalln("[x]", "log file path error.", logFileError.Error())
+		}
+		log.Println("[√]", "open test log file success. path:", logPath)
+	}*/
+
+	switch args[1] {
+	case "-listen":
+		if argc < 3 {
+			log.Fatalln(`-listen need two arguments, like "nb -listen 1997 2017".`)
+		}
+		port1 := checkPort(args[2])
+		port2 := checkPort(args[3])
+		log.Println("[√]", "start to listen port:", port1, "and port:", port2)
+		port2port(port1, port2)
+		break
+	case "-tran":
+		if argc < 3 {
+			log.Fatalln(`-tran need two arguments, like "nb -tran 1997 192.168.1.2:3389".`)
+		}
+		port := checkPort(args[2])
+		var remoteAddress string
+		if checkIp(args[3]) {
+			remoteAddress = args[3]
+		}
+		split := strings.SplitN(remoteAddress, ":", 2)
+		log.Println("[√]", "start to transmit address:", remoteAddress, "to address:", split[0]+":"+port)
+		port2host(port, remoteAddress)
+		break
+	case "-slave":
+		if argc < 3 {
+			log.Fatalln(`-slave need two arguments, like "nb -slave 127.0.0.1:3389 8.8.8.8:1997".`)
+		}
+		var address1, address2 string
+		checkIp(args[2])
+		if checkIp(args[2]) {
+			address1 = args[2]
+		}
+		checkIp(args[3])
+		if checkIp(args[3]) {
+			address2 = args[3]
+		}
+		log.Println("[√]", "start to connect address:", address1, "and address:", address2)
+		host2host(address1, address2)
+		break
+	default:
+		printHelp()
+	}
+}
+
+func printWelcome() {
+	fmt.Println("+----------------------------------------------------------------+")
+	fmt.Println("| Welcome to use NATBypass Ver1.0.0 .                            |")
+	fmt.Println("| Code by cw1997 at 2017-10-19 03:59:51                          |")
+	fmt.Println("| If you have some problem when you use the tool,                |")
+	fmt.Println("| please submit issue at : https://github.com/cw1997/NATBypass . |")
+	fmt.Println("+----------------------------------------------------------------+")
+	fmt.Println()
+	// sleep one second because the fmt is not thread-safety.
+	// if not to do this, fmt.Print will print after the log.Print.
+	time.Sleep(time.Second)
+}
+func printHelp() {
+	fmt.Println(`usage: "-listen port1 port2" example: "nb -listen 1997 2017" `)
+	fmt.Println(`       "-tran port1 ip:port2" example: "nb -tran 1997 192.168.1.2:3389" `)
+	fmt.Println(`       "-slave ip1:port1 ip2:port2" example: "nb -slave 127.0.0.1:3389 8.8.8.8:1997" `)
+	fmt.Println(`============================================================`)
+	fmt.Println(`optional argument: "-log logpath" . example: "nb -listen 1997 2017 -log d:/nb" `)
+	fmt.Println(`log filename format: Y_m_d_H_i_s-agrs1-args2-args3.log`)
+	fmt.Println(`============================================================`)
+	fmt.Println(`if you want more help, please read "README.md". `)
+}
+
+func checkPort(port string) string {
+	PortNum, err := strconv.Atoi(port)
+	if err != nil {
+		log.Fatalln("[x]", "port should be a number")
+	}
+	if PortNum < 1 || PortNum > 65535 {
+		log.Fatalln("[x]", "port should be a number and the range is [1,65536)")
+	}
+	return port
+}
+
+func checkIp(address string) bool {
+	ipAndPort := strings.Split(address, ":")
+	if len(ipAndPort) != 2 {
+		log.Fatalln("[x]", "address error. should be a string like [ip:port]. ")
+	}
+	ip := ipAndPort[0]
+	port := ipAndPort[1]
+	checkPort(port)
+	pattern := `^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$`
+	ok, err := regexp.MatchString(pattern, ip)
+	if err != nil || !ok {
+		log.Fatalln("[x]", "ip error. ")
+	}
+	return ok
+}
+
+func port2port(port1 string, port2 string) {
+	listen1 := start_server("0.0.0.0:" + port1)
+	listen2 := start_server("0.0.0.0:" + port2)
+	log.Println("[√]", "listen port:", port1, "and", port2, "success. waiting for client...")
+	for {
+		conn1 := accept(listen1)
+		conn2 := accept(listen2)
+		if conn1 == nil || conn2 == nil {
+			log.Println("[x]", "accept client faild. retry in ", timeout, " seconds. ")
+			time.Sleep(timeout * time.Second)
+			continue
+		}
+		forward(conn1, conn2)
+	}
+}
+
+func port2host(allowPort string, targetAddress string) {
+	server := start_server("0.0.0.0:" + allowPort)
+	for {
+		conn := accept(server)
+		if conn == nil {
+			continue
+		}
+		//println(targetAddress)
+		go func(targetAddress string) {
+			log.Println("[+]", "start connect host:["+targetAddress+"]")
+			target, err := net.Dial("tcp", targetAddress)
+			if err != nil {
+				// temporarily unavailable, don't use fatal.
+				log.Println("[x]", "connect target address ["+targetAddress+"] faild. retry in ", timeout, "seconds. ")
+				conn.Close()
+				log.Println("[←]", "close the connect at local:["+conn.LocalAddr().String()+"] and remote:["+conn.RemoteAddr().String()+"]")
+				time.Sleep(timeout * time.Second)
+				return
+			}
+			log.Println("[→]", "connect target address ["+targetAddress+"] success.")
+			forward(target, conn)
+		}(targetAddress)
+	}
+}
+
+func host2host(address1, address2 string) {
+	for {
+		log.Println("[+]", "try to connect host:["+address1+"] and ["+address2+"]")
+		var host1, host2 net.Conn
+		var err error
+		for {
+			host1, err = net.Dial("tcp", address1)
+			if err == nil {
+				log.Println("[→]", "connect ["+address1+"] success.")
+				break
+			} else {
+				log.Println("[x]", "connect target address ["+address1+"] faild. retry in ", timeout, " seconds. ")
+				time.Sleep(timeout * time.Second)
+			}
+		}
+		for {
+			host2, err = net.Dial("tcp", address2)
+			if err == nil {
+				log.Println("[→]", "connect ["+address2+"] success.")
+				break
+			} else {
+				log.Println("[x]", "connect target address ["+address2+"] faild. retry in ", timeout, " seconds. ")
+				time.Sleep(timeout * time.Second)
+			}
+		}
+		forward(host1, host2)
+	}
+}
+
+func start_server(address string) net.Listener {
+	log.Println("[+]", "try to start server on:["+address+"]")
+	server, err := net.Listen("tcp", address)
+	if err != nil {
+		log.Fatalln("[x]", "listen address ["+address+"] faild.")
+	}
+	log.Println("[√]", "start listen at address:["+address+"]")
+	return server
+	/*defer server.Close()
+
+	for {
+		conn, err := server.Accept()
+		log.Println("accept a new client. remote address:[" + conn.RemoteAddr().String() +
+			"], local address:[" + conn.LocalAddr().String() + "]")
+		if err != nil {
+			log.Println("accept a new client faild.", err.Error())
+			continue
+		}
+		//go recvConnMsg(conn)
+	}*/
+}
+
+func accept(listener net.Listener) net.Conn {
+	conn, err := listener.Accept()
+	if err != nil {
+		log.Println("[x]", "accept connect ["+conn.RemoteAddr().String()+"] faild.", err.Error())
+		return nil
+	}
+	log.Println("[√]", "accept a new client. remote address:["+conn.RemoteAddr().String()+"], local address:["+conn.LocalAddr().String()+"]")
+	return conn
+}
+
+func forward(conn1 net.Conn, conn2 net.Conn) {
+	log.Printf("[+] start transmit. [%s],[%s] <-> [%s],[%s] \n", conn1.LocalAddr().String(), conn1.RemoteAddr().String(), conn2.LocalAddr().String(), conn2.RemoteAddr().String())
+	var wg sync.WaitGroup
+	// wait tow goroutines
+	wg.Add(2)
+	go connCopy(conn1, conn2, &wg)
+	go connCopy(conn2, conn1, &wg)
+	//blocking when the wg is locked
+	wg.Wait()
+}
+
+func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup) {
+	//TODO:log, record the data from conn1 and conn2.
+	logFile := openLog(conn1.LocalAddr().String(), conn1.RemoteAddr().String(), conn2.LocalAddr().String(), conn2.RemoteAddr().String())
+	if logFile != nil {
+		w := io.MultiWriter(conn1, logFile)
+		io.Copy(w, conn2)
+	} else {
+		io.Copy(conn1, conn2)
+	}
+	conn1.Close()
+	log.Println("[←]", "close the connect at local:["+conn1.LocalAddr().String()+"] and remote:["+conn1.RemoteAddr().String()+"]")
+	//conn2.Close()
+	//log.Println("[←]", "close the connect at local:["+conn2.LocalAddr().String()+"] and remote:["+conn2.RemoteAddr().String()+"]")
+	wg.Done()
+}
+func openLog(address1, address2, address3, address4 string) *os.File {
+	args := os.Args
+	argc := len(os.Args)
+	var logFileError error
+	var logFile *os.File
+	if argc > 5 && args[4] == "-log" {
+		address1 = strings.Replace(address1, ":", "_", -1)
+		address2 = strings.Replace(address2, ":", "_", -1)
+		address3 = strings.Replace(address3, ":", "_", -1)
+		address4 = strings.Replace(address4, ":", "_", -1)
+		timeStr := time.Now().Format("2006_01_02_15_04_05") // "2006-01-02 15:04:05"
+		logPath := args[5] + "/" + timeStr + args[1] + "-" + address1 + "_" + address2 + "-" + address3 + "_" + address4 + ".log"
+		logPath = strings.Replace(logPath, `\`, "/", -1)
+		logPath = strings.Replace(logPath, "//", "/", -1)
+		logFile, logFileError = os.OpenFile(logPath, os.O_APPEND|os.O_CREATE, 0666)
+		if logFileError != nil {
+			log.Fatalln("[x]", "log file path error.", logFileError.Error())
+		}
+		log.Println("[√]", "open test log file success. path:", logPath)
+	}
+	return logFile
+}

+ 69 - 0
mod/tcpprox/tcpprox.go

@@ -0,0 +1,69 @@
+package tcpprox
+
+import "imuslab.com/zoraxy/mod/database"
+
+/*
+	TCP Proxy
+
+	Forward port from one port to another
+	Also accept active connection and passive
+	connection
+*/
+
+const (
+	ProxyMode_Listen    = 0
+	ProxyMode_Transport = 1
+	ProxyMode_Starter   = 2
+)
+
+type ProxyRelayConfig struct {
+	UUID     string    //A UUIDv4 representing this config
+	Name     string    //Name of the config
+	Running  bool      //If the service is running
+	PortA    int       //Ports A (config depends on mode)
+	PortB    int       //Ports B (config depends on mode)
+	Mode     int       //Operation Mode
+	Timeout  int       //Timeout for connection
+	StopChan chan bool //Stop channel to stop the listener
+}
+
+type Options struct {
+	Database *database.Database
+}
+
+type Manager struct {
+	//Config and stores
+	Options *Options
+	Configs []*ProxyRelayConfig
+
+	//Realtime Statistics
+	Connections               int   //currently connected connect counts
+	AccumulatedByteTransfered int64 //The total number of bytes transfered
+}
+
+func NewTCProxy(options *Options) *Manager {
+	options.Database.NewTable("tcprox")
+
+	previousRules := []*ProxyRelayConfig{}
+	if options.Database.KeyExists("tcprox", "rules") {
+		options.Database.Read("tcprox", "rules", &previousRules)
+	}
+
+	return &Manager{
+		Options:     options,
+		Configs:     previousRules,
+		Connections: 0,
+	}
+}
+
+func (m *Manager) NewConfig(config *ProxyRelayConfig) error {
+	return nil
+}
+
+func (m *Manager) RemoveConfig(configUUID string) error {
+	return nil
+}
+
+func (m *Manager) SaveConfigToDatabase() {
+	m.Options.Database.Write("tcprox", "rules", m.Configs)
+}

+ 9 - 0
reverseproxy.go

@@ -325,6 +325,15 @@ func HandleIncomingPortSet(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	//Check if it is identical as proxy root (recursion!)
+	proxyRoot := strings.TrimSuffix(dynamicProxyRouter.Root.Domain, "/")
+	if strings.HasPrefix(proxyRoot, "localhost:"+strconv.Itoa(newIncomingPortInt)) || strings.HasPrefix(proxyRoot, "127.0.0.1:"+strconv.Itoa(newIncomingPortInt)) {
+		//Listening port is same as proxy root
+		//Not allow recursive settings
+		utils.SendErrorResponse(w, "Recursive listening port! Check your proxy root settings.")
+		return
+	}
+
 	//Stop and change the setting of the reverse proxy service
 	if dynamicProxyRouter.Running {
 		dynamicProxyRouter.StopProxyService()

+ 2 - 2
web/components/stats.html

@@ -16,7 +16,7 @@
         <!-- Client IP Analysis -->
         <div class="ui stackable grid">
             <div class="eight wide column">
-                <h3>Request Client IP Versions</h3>
+                <h3>Requests IP Version</h3>
                 <p>The version of Internet Protocol that the client is using. If the request client is pass through a DNS proxy like CloudFlare, 
                     the CloudFlare proxy server address will be filtered and only the first value in the RemoteAddress field will be analysised.</p>
                 <div>
@@ -24,7 +24,7 @@
                 </div>
             </div>
             <div class="eight wide column">
-                <h3>Request Origin Counts</h3>
+                <h3>Request Origins</h3>
                 <p>Top 25 request origin sorted by request count</p>
                 <div style="height: 500px; overflow-y: auto;">
                     <table class="ui unstackable striped celled table">

+ 1 - 0
web/components/status.html

@@ -295,6 +295,7 @@
         $.post("/api/proxy/setIncoming", {incoming: newPortValue}, function(data){
             if (data.error != undefined){
                 msgbox(data.error, false, 5000);
+                return;
             }
             msgbox("Setting Updated");
             initRPStaste();

+ 2 - 2
web/script/useragent.js

@@ -121,7 +121,7 @@
         {s:'OS/2', r:/OS\/2/},
         //Special agents
         {s:'Search Bot', r:/(nuhk|CensysInspect|facebookexternalhit|Twitterbot|AhrefsBot|Palo Alto|InternetMeasurement|PetalBot|coccocbot|MJ12bot|Googlebot|bingbot|Yammybot|YandexBot|SeznamBot|SemrushBot|Openbot|Slurp|Sogou web spider|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/},
-        {s: 'Auto Scripts', r:/(Go-http-client|cpp-httplib|python-requests|Java|zgrab|ALittle Client|)/},
+        {s: 'Scripts', r:/(Go-http-client|cpp-httplib|python-requests|Java|zgrab|ALittle Client|)/},
     ];
     for (var id in clientStrings) {
         var cs = clientStrings[id];
@@ -193,7 +193,7 @@ function getOSColorCode(browserName){
         'BeOS': '#8F8F8F',
         'OS/2': '#D8BFD8',
         'Search Bot': '#F6A821',
-        'Auto Scripts': '#B8B8B8',
+        'Scripts': '#B8B8B8',
     }
 
     return browserColors[browserName] || "#e0e0e0";