mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-06 07:37:21 +02:00
Fixed memory leaking
+ Patch on memory leaking for Windows netstat module (do not effect any of the previous non Windows builds) + Fixed potential memory leak in acme handler logic + Added "do you want to get a TLS certificate for this subdomain?" dialog when a new subdomain proxy rule is created
This commit is contained in:
parent
5038429a70
commit
52d3b2f8c2
@ -66,6 +66,7 @@ func acmeRegisterSpecialRoutingRule() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resBody, err := ioutil.ReadAll(res.Body)
|
resBody, err := ioutil.ReadAll(res.Body)
|
||||||
|
defer res.Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error reading: %s\n", err)
|
fmt.Printf("error reading: %s\n", err)
|
||||||
return
|
return
|
||||||
|
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/pprof"
|
||||||
|
|
||||||
"imuslab.com/zoraxy/mod/acme/acmewizard"
|
"imuslab.com/zoraxy/mod/acme/acmewizard"
|
||||||
"imuslab.com/zoraxy/mod/auth"
|
"imuslab.com/zoraxy/mod/auth"
|
||||||
@ -166,6 +167,9 @@ func initAPIs() {
|
|||||||
http.HandleFunc("/api/conf/export", ExportConfigAsZip)
|
http.HandleFunc("/api/conf/export", ExportConfigAsZip)
|
||||||
http.HandleFunc("/api/conf/import", ImportConfigFromZip)
|
http.HandleFunc("/api/conf/import", ImportConfigFromZip)
|
||||||
|
|
||||||
|
//Debug
|
||||||
|
authRouter.HandleFunc("/api/info/pprof", pprof.Index)
|
||||||
|
|
||||||
//If you got APIs to add, append them here
|
//If you got APIs to add, append them here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
39
src/geoip.go
39
src/geoip.go
@ -1,39 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/oschwald/geoip2-golang"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getCountryCodeFromRequest(r *http.Request) string {
|
|
||||||
countryCode := ""
|
|
||||||
|
|
||||||
// Get the IP address of the user from the request headers
|
|
||||||
ipAddress := r.Header.Get("X-Forwarded-For")
|
|
||||||
if ipAddress == "" {
|
|
||||||
ipAddress = strings.Split(r.RemoteAddr, ":")[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open the GeoIP database
|
|
||||||
db, err := geoip2.Open("./tmp/GeoIP2-Country.mmdb")
|
|
||||||
if err != nil {
|
|
||||||
// Handle the error
|
|
||||||
return countryCode
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
// Look up the country code for the IP address
|
|
||||||
record, err := db.Country(net.ParseIP(ipAddress))
|
|
||||||
if err != nil {
|
|
||||||
// Handle the error
|
|
||||||
return countryCode
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the ISO country code from the record
|
|
||||||
countryCode = record.Country.IsoCode
|
|
||||||
|
|
||||||
return countryCode
|
|
||||||
}
|
|
@ -41,7 +41,7 @@ var ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port")
|
|||||||
var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)")
|
var acmeAutoRenewInterval = flag.Int("autorenew", 86400, "ACME auto TLS/SSL certificate renew check interval (seconds)")
|
||||||
var (
|
var (
|
||||||
name = "Zoraxy"
|
name = "Zoraxy"
|
||||||
version = "2.6.5"
|
version = "2.6.6"
|
||||||
nodeUUID = "generic"
|
nodeUUID = "generic"
|
||||||
development = false //Set this to false to use embedded web fs
|
development = false //Set this to false to use embedded web fs
|
||||||
bootTime = time.Now().Unix()
|
bootTime = time.Now().Unix()
|
||||||
|
@ -14,10 +14,6 @@ import (
|
|||||||
|
|
||||||
var onExitFlushLoop func()
|
var onExitFlushLoop func()
|
||||||
|
|
||||||
const (
|
|
||||||
defaultTimeout = time.Minute * 5
|
|
||||||
)
|
|
||||||
|
|
||||||
// ReverseProxy is an HTTP Handler that takes an incoming request and
|
// ReverseProxy is an HTTP Handler that takes an incoming request and
|
||||||
// sends it to another server, proxying the response back to the
|
// sends it to another server, proxying the response back to the
|
||||||
// client, support http, also support https tunnel using http.hijacker
|
// client, support http, also support https tunnel using http.hijacker
|
||||||
|
@ -183,6 +183,5 @@ func (h *ProxyHandler) logRequest(r *http.Request, succ bool, statusCode int, fo
|
|||||||
}
|
}
|
||||||
h.Parent.Option.StatisticCollector.RecordRequest(requestInfo)
|
h.Parent.Option.StatisticCollector.RecordRequest(requestInfo)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,6 +213,7 @@ func GetNetworkInterfaceStats() (int64, int64, error) {
|
|||||||
out, err := cmd.Output()
|
out, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
callbackChan <- wmicResult{0, 0, err}
|
callbackChan <- wmicResult{0, 0, err}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//Filter out the first line
|
//Filter out the first line
|
||||||
@ -251,18 +252,16 @@ func GetNetworkInterfaceStats() (int64, int64, error) {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
//Spawn a timer to terminate the cmd process if timeout
|
//Spawn a timer to terminate the cmd process if timeout
|
||||||
var timer *time.Timer
|
time.Sleep(3 * time.Second)
|
||||||
timer = time.AfterFunc(3*time.Second, func() {
|
if cmd != nil && cmd.Process != nil {
|
||||||
timer.Stop()
|
cmd.Process.Kill()
|
||||||
if cmd != nil && cmd.Process != nil {
|
|
||||||
cmd.Process.Kill()
|
|
||||||
}
|
|
||||||
callbackChan <- wmicResult{0, 0, errors.New("wmic execution timeout")}
|
callbackChan <- wmicResult{0, 0, errors.New("wmic execution timeout")}
|
||||||
})
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
result := wmicResult{}
|
result := wmicResult{}
|
||||||
result = <-callbackChan
|
result = <-callbackChan
|
||||||
|
cmd = nil
|
||||||
if result.Err != nil {
|
if result.Err != nil {
|
||||||
log.Println("Unable to extract NIC info from wmic: " + result.Err.Error())
|
log.Println("Unable to extract NIC info from wmic: " + result.Err.Error())
|
||||||
}
|
}
|
||||||
|
@ -93,8 +93,6 @@ func (m *Monitor) ExecuteUptimeCheck() {
|
|||||||
Latency: laterncy,
|
Latency: laterncy,
|
||||||
}
|
}
|
||||||
|
|
||||||
//fmt.Println(thisRecord)
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log.Println("Unknown protocol: " + target.Protocol + ". Skipping")
|
log.Println("Unknown protocol: " + target.Protocol + ". Skipping")
|
||||||
continue
|
continue
|
||||||
@ -238,9 +236,11 @@ func getWebsiteStatus(url string) (int, error) {
|
|||||||
}
|
}
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
status_code := resp.StatusCode
|
||||||
|
return status_code, nil
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
status_code := resp.StatusCode
|
status_code := resp.StatusCode
|
||||||
resp.Body.Close()
|
|
||||||
return status_code, nil
|
return status_code, nil
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"encoding/base64"
|
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@ -131,17 +128,6 @@ func TimeToString(targetTime time.Time) string {
|
|||||||
return targetTime.Format("2006-01-02 15:04:05")
|
return targetTime.Format("2006-01-02 15:04:05")
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadImageAsBase64(filepath string) (string, error) {
|
|
||||||
if !FileExists(filepath) {
|
|
||||||
return "", errors.New("File not exists")
|
|
||||||
}
|
|
||||||
f, _ := os.Open(filepath)
|
|
||||||
reader := bufio.NewReader(f)
|
|
||||||
content, _ := io.ReadAll(reader)
|
|
||||||
encoded := base64.StdEncoding.EncodeToString(content)
|
|
||||||
return string(encoded), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use for redirections
|
// Use for redirections
|
||||||
func ConstructRelativePathFromRequestURL(requestURI string, redirectionLocation string) string {
|
func ConstructRelativePathFromRequestURL(requestURI string, redirectionLocation string) string {
|
||||||
if strings.Count(requestURI, "/") == 1 {
|
if strings.Count(requestURI, "/") == 1 {
|
||||||
|
@ -128,7 +128,8 @@ func startupSequence() {
|
|||||||
BuildVersion: version,
|
BuildVersion: version,
|
||||||
}, "")
|
}, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.Println("Unable to startup mDNS service.")
|
||||||
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Start initial scanning
|
//Start initial scanning
|
||||||
|
@ -308,7 +308,7 @@
|
|||||||
<div class="ui message">
|
<div class="ui message">
|
||||||
<i class="ui info circle icon"></i> IP Address support the following formats
|
<i class="ui info circle icon"></i> IP Address support the following formats
|
||||||
<div class="ui bulleted list">
|
<div class="ui bulleted list">
|
||||||
<div class="item">Fixed IP Address (e.g. 192.128.4.100)</div>
|
<div class="item">Fixed IP Address (e.g. 192.128.4.100 or fe80::210:5aff:feaa:20a2)</div>
|
||||||
<div class="item">IP Wildcard (e.g. 172.164.*.*)</div>
|
<div class="item">IP Wildcard (e.g. 172.164.*.*)</div>
|
||||||
<div class="item">CIDR String (e.g. 128.32.0.1/16)</div>
|
<div class="item">CIDR String (e.g. 128.32.0.1/16)</div>
|
||||||
</div>
|
</div>
|
||||||
@ -625,7 +625,7 @@
|
|||||||
<div class="ui message">
|
<div class="ui message">
|
||||||
<i class="ui info circle icon"></i> IP Address support the following formats
|
<i class="ui info circle icon"></i> IP Address support the following formats
|
||||||
<div class="ui bulleted list">
|
<div class="ui bulleted list">
|
||||||
<div class="item">Fixed IP Address (e.g. 192.128.4.100)</div>
|
<div class="item">Fixed IP Address (e.g. 192.128.4.100 or fe80::210:5aff:feaa:20a2)</div>
|
||||||
<div class="item">IP Wildcard (e.g. 172.164.*.*)</div>
|
<div class="item">IP Wildcard (e.g. 172.164.*.*)</div>
|
||||||
<div class="item">CIDR String (e.g. 128.32.0.1/16)</div>
|
<div class="item">CIDR String (e.g. 128.32.0.1/16)</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -172,13 +172,27 @@
|
|||||||
//OK
|
//OK
|
||||||
listVdirs();
|
listVdirs();
|
||||||
listSubd();
|
listSubd();
|
||||||
msgbox("Proxy Endpoint Added");
|
|
||||||
|
|
||||||
//Clear old data
|
//Clear old data
|
||||||
$("#rootname").val("");
|
$("#rootname").val("");
|
||||||
$("#proxyDomain").val("");
|
$("#proxyDomain").val("");
|
||||||
credentials = [];
|
credentials = [];
|
||||||
updateTable();
|
updateTable();
|
||||||
|
|
||||||
|
//Check if it is a new subdomain and TLS enabled
|
||||||
|
if (type == "subd" && $("#tls").checkbox("is checked")){
|
||||||
|
confirmBox("Request new SSL Cert for this subdomain?", function(choice){
|
||||||
|
if (choice == true){
|
||||||
|
//Get a new cert using ACME
|
||||||
|
msgbox("Requesting certificate via Let's Encrypt...");
|
||||||
|
console.log("Trying to get a new certificate via ACME");
|
||||||
|
obtainCertificate(rootname);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
msgbox("Proxy Endpoint Added");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -437,4 +451,67 @@
|
|||||||
}));
|
}));
|
||||||
showSideWrapper("snippet/basicAuthEditor.html?t=" + Date.now() + "#" + payload);
|
showSideWrapper("snippet/basicAuthEditor.html?t=" + Date.now() + "#" + payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Obtain Certificate via ACME
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Load the ACME email from server side
|
||||||
|
let acmeEmail = "";
|
||||||
|
$.get("/api/acme/autoRenew/email", function(data){
|
||||||
|
if (data != "" && data != undefined && data != null){
|
||||||
|
acmeEmail = data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Obtain certificate from API, only support one domain
|
||||||
|
function obtainCertificate(domains) {
|
||||||
|
let filename = "";
|
||||||
|
let email = acmeEmail;
|
||||||
|
if (acmeEmail == ""){
|
||||||
|
let rootDomain = domains.split(".").pop();
|
||||||
|
email = "admin@" + rootDomain;
|
||||||
|
}
|
||||||
|
if (filename.trim() == "" && !domains.includes(",")){
|
||||||
|
//Zoraxy filename are the matching name for domains.
|
||||||
|
//Use the same as domains
|
||||||
|
filename = domains;
|
||||||
|
}else if (filename != "" && !domains.includes(",")){
|
||||||
|
//Invalid settings. Force the filename to be same as domain
|
||||||
|
//if there are only 1 domain
|
||||||
|
filename = domains;
|
||||||
|
}else{
|
||||||
|
parent.msgbox("Filename cannot be empty for certs containing multiple domains.")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/acme/obtainCert",
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
domains: domains,
|
||||||
|
filename: filename,
|
||||||
|
email: email,
|
||||||
|
ca: "Let's Encrypt",
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
if (response.error) {
|
||||||
|
console.log("Error:", response.error);
|
||||||
|
// Show error message
|
||||||
|
msgbox(response.error, false, 12000);
|
||||||
|
} else {
|
||||||
|
console.log("Certificate installed successfully");
|
||||||
|
// Show success message
|
||||||
|
msgbox("Certificate installed successfully");
|
||||||
|
|
||||||
|
// Renew the parent certificate list
|
||||||
|
initManagedDomainCertificateList();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(error) {
|
||||||
|
console.log("Failed to install certificate:", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
@ -116,7 +116,7 @@ body{
|
|||||||
}
|
}
|
||||||
|
|
||||||
#confirmBox .ui.progress .bar{
|
#confirmBox .ui.progress .bar{
|
||||||
background: #ffe32b !important;
|
background: #a9d1f3 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#confirmBox .confirmBoxBody .button{
|
#confirmBox .confirmBoxBody .button{
|
||||||
|
@ -83,8 +83,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<h3>Manual Renew</h3>
|
<h3>Generate New Certificate</h3>
|
||||||
<p>Pick a certificate below to force renew</p>
|
<p>Enter a new / existing domain(s) to request new certificate(s)</p>
|
||||||
<div class="ui form">
|
<div class="ui form">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Domain(s)</label>
|
<label>Domain(s)</label>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user