mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-03 06:07:20 +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)
|
||||
defer res.Body.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("error reading: %s\n", err)
|
||||
return
|
||||
|
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
|
||||
"imuslab.com/zoraxy/mod/acme/acmewizard"
|
||||
"imuslab.com/zoraxy/mod/auth"
|
||||
@ -166,6 +167,9 @@ func initAPIs() {
|
||||
http.HandleFunc("/api/conf/export", ExportConfigAsZip)
|
||||
http.HandleFunc("/api/conf/import", ImportConfigFromZip)
|
||||
|
||||
//Debug
|
||||
authRouter.HandleFunc("/api/info/pprof", pprof.Index)
|
||||
|
||||
//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 (
|
||||
name = "Zoraxy"
|
||||
version = "2.6.5"
|
||||
version = "2.6.6"
|
||||
nodeUUID = "generic"
|
||||
development = false //Set this to false to use embedded web fs
|
||||
bootTime = time.Now().Unix()
|
||||
|
@ -14,10 +14,6 @@ import (
|
||||
|
||||
var onExitFlushLoop func()
|
||||
|
||||
const (
|
||||
defaultTimeout = time.Minute * 5
|
||||
)
|
||||
|
||||
// ReverseProxy is an HTTP Handler that takes an incoming request and
|
||||
// sends it to another server, proxying the response back to the
|
||||
// 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)
|
||||
}()
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -213,6 +213,7 @@ func GetNetworkInterfaceStats() (int64, int64, error) {
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
callbackChan <- wmicResult{0, 0, err}
|
||||
return
|
||||
}
|
||||
|
||||
//Filter out the first line
|
||||
@ -251,18 +252,16 @@ func GetNetworkInterfaceStats() (int64, int64, error) {
|
||||
|
||||
go func() {
|
||||
//Spawn a timer to terminate the cmd process if timeout
|
||||
var timer *time.Timer
|
||||
timer = time.AfterFunc(3*time.Second, func() {
|
||||
timer.Stop()
|
||||
if cmd != nil && cmd.Process != nil {
|
||||
cmd.Process.Kill()
|
||||
}
|
||||
time.Sleep(3 * time.Second)
|
||||
if cmd != nil && cmd.Process != nil {
|
||||
cmd.Process.Kill()
|
||||
callbackChan <- wmicResult{0, 0, errors.New("wmic execution timeout")}
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
result := wmicResult{}
|
||||
result = <-callbackChan
|
||||
cmd = nil
|
||||
if result.Err != nil {
|
||||
log.Println("Unable to extract NIC info from wmic: " + result.Err.Error())
|
||||
}
|
||||
|
@ -93,8 +93,6 @@ func (m *Monitor) ExecuteUptimeCheck() {
|
||||
Latency: laterncy,
|
||||
}
|
||||
|
||||
//fmt.Println(thisRecord)
|
||||
|
||||
} else {
|
||||
log.Println("Unknown protocol: " + target.Protocol + ". Skipping")
|
||||
continue
|
||||
@ -238,9 +236,11 @@ func getWebsiteStatus(url string) (int, error) {
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
status_code := resp.StatusCode
|
||||
return status_code, nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
status_code := resp.StatusCode
|
||||
resp.Body.Close()
|
||||
return status_code, nil
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -131,17 +128,6 @@ func TimeToString(targetTime time.Time) string {
|
||||
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
|
||||
func ConstructRelativePathFromRequestURL(requestURI string, redirectionLocation string) string {
|
||||
if strings.Count(requestURI, "/") == 1 {
|
||||
|
@ -128,7 +128,8 @@ func startupSequence() {
|
||||
BuildVersion: version,
|
||||
}, "")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Println("Unable to startup mDNS service.")
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
//Start initial scanning
|
||||
|
@ -308,7 +308,7 @@
|
||||
<div class="ui message">
|
||||
<i class="ui info circle icon"></i> IP Address support the following formats
|
||||
<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">CIDR String (e.g. 128.32.0.1/16)</div>
|
||||
</div>
|
||||
@ -625,7 +625,7 @@
|
||||
<div class="ui message">
|
||||
<i class="ui info circle icon"></i> IP Address support the following formats
|
||||
<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">CIDR String (e.g. 128.32.0.1/16)</div>
|
||||
</div>
|
||||
|
@ -172,13 +172,27 @@
|
||||
//OK
|
||||
listVdirs();
|
||||
listSubd();
|
||||
msgbox("Proxy Endpoint Added");
|
||||
|
||||
|
||||
//Clear old data
|
||||
$("#rootname").val("");
|
||||
$("#proxyDomain").val("");
|
||||
credentials = [];
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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>
|
@ -116,7 +116,7 @@ body{
|
||||
}
|
||||
|
||||
#confirmBox .ui.progress .bar{
|
||||
background: #ffe32b !important;
|
||||
background: #a9d1f3 !important;
|
||||
}
|
||||
|
||||
#confirmBox .confirmBoxBody .button{
|
||||
|
@ -83,8 +83,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui divider"></div>
|
||||
<h3>Manual Renew</h3>
|
||||
<p>Pick a certificate below to force renew</p>
|
||||
<h3>Generate New Certificate</h3>
|
||||
<p>Enter a new / existing domain(s) to request new certificate(s)</p>
|
||||
<div class="ui form">
|
||||
<div class="field">
|
||||
<label>Domain(s)</label>
|
||||
|
Loading…
x
Reference in New Issue
Block a user