mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-03 06:07:20 +02:00
commit
4d163fe80f
@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
"github.com/go-acme/lego/v4/certcrypto"
|
"github.com/go-acme/lego/v4/certcrypto"
|
||||||
"github.com/go-acme/lego/v4/certificate"
|
"github.com/go-acme/lego/v4/certificate"
|
||||||
|
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||||
"github.com/go-acme/lego/v4/challenge/http01"
|
"github.com/go-acme/lego/v4/challenge/http01"
|
||||||
"github.com/go-acme/lego/v4/lego"
|
"github.com/go-acme/lego/v4/lego"
|
||||||
"github.com/go-acme/lego/v4/registration"
|
"github.com/go-acme/lego/v4/registration"
|
||||||
@ -29,12 +30,20 @@ import (
|
|||||||
"imuslab.com/zoraxy/mod/utils"
|
"imuslab.com/zoraxy/mod/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var defaultNameservers = []string{
|
||||||
|
"8.8.8.8:53", // Google DNS
|
||||||
|
"8.8.4.4:53", // Google DNS
|
||||||
|
"1.1.1.1:53", // Cloudflare DNS
|
||||||
|
"1.0.0.1:53", // Cloudflare DNS
|
||||||
|
}
|
||||||
|
|
||||||
type CertificateInfoJSON struct {
|
type CertificateInfoJSON struct {
|
||||||
AcmeName string `json:"acme_name"` //ACME provider name
|
AcmeName string `json:"acme_name"` //ACME provider name
|
||||||
AcmeUrl string `json:"acme_url"` //Custom ACME URL (if any)
|
AcmeUrl string `json:"acme_url"` //Custom ACME URL (if any)
|
||||||
SkipTLS bool `json:"skip_tls"` //Skip TLS verification of upstream
|
SkipTLS bool `json:"skip_tls"` //Skip TLS verification of upstream
|
||||||
UseDNS bool `json:"dns"` //Use DNS challenge
|
UseDNS bool `json:"dns"` //Use DNS challenge
|
||||||
PropTimeout int `json:"prop_time"` //Propagation timeout
|
PropTimeout int `json:"prop_time"` //Propagation timeout
|
||||||
|
DNSServers []string `json:"dnsServers"` // DNS servers
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACMEUser represents a user in the ACME system.
|
// ACMEUser represents a user in the ACME system.
|
||||||
@ -94,7 +103,7 @@ func (a *ACMEHandler) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ObtainCert obtains a certificate for the specified domains.
|
// ObtainCert obtains a certificate for the specified domains.
|
||||||
func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email string, caName string, caUrl string, skipTLS bool, useDNS bool, propagationTimeout int) (bool, error) {
|
func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email string, caName string, caUrl string, skipTLS bool, useDNS bool, propagationTimeout int, dnsServers string) (bool, error) {
|
||||||
a.Logf("Obtaining certificate for: "+strings.Join(domains, ", "), nil)
|
a.Logf("Obtaining certificate for: "+strings.Join(domains, ", "), nil)
|
||||||
|
|
||||||
// generate private key
|
// generate private key
|
||||||
@ -164,15 +173,31 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load certificate info from JSON file
|
||||||
|
certInfo, err := LoadCertInfoJSON(fmt.Sprintf("./conf/certs/%s.json", certificateName))
|
||||||
|
if err == nil {
|
||||||
|
useDNS = certInfo.UseDNS
|
||||||
|
if dnsServers == "" && certInfo.DNSServers != nil && len(certInfo.DNSServers) > 0 {
|
||||||
|
dnsServers = strings.Join(certInfo.DNSServers, ",")
|
||||||
|
}
|
||||||
|
propagationTimeout = certInfo.PropTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean DNS servers
|
||||||
|
dnsNameservers := strings.Split(dnsServers, ",")
|
||||||
|
for i := range dnsNameservers {
|
||||||
|
dnsNameservers[i] = strings.TrimSpace(dnsNameservers[i])
|
||||||
|
}
|
||||||
|
|
||||||
// setup how to receive challenge
|
// setup how to receive challenge
|
||||||
if useDNS {
|
if useDNS {
|
||||||
if !a.Database.TableExists("acme") {
|
if !a.Database.TableExists("acme") {
|
||||||
a.Database.NewTable("acme")
|
a.Database.NewTable("acme")
|
||||||
return false, errors.New("DNS Provider and DNS Credenital configuration required for ACME Provider (Error -1)")
|
return false, errors.New("DNS Provider and DNS Credential configuration required for ACME Provider (Error -1)")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !a.Database.KeyExists("acme", certificateName+"_dns_provider") || !a.Database.KeyExists("acme", certificateName+"_dns_credentials") {
|
if !a.Database.KeyExists("acme", certificateName+"_dns_provider") || !a.Database.KeyExists("acme", certificateName+"_dns_credentials") {
|
||||||
return false, errors.New("DNS Provider and DNS Credenital configuration required for ACME Provider (Error -2)")
|
return false, errors.New("DNS Provider and DNS Credential configuration required for ACME Provider (Error -2)")
|
||||||
}
|
}
|
||||||
|
|
||||||
var dnsCredentials string
|
var dnsCredentials string
|
||||||
@ -195,7 +220,13 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = client.Challenge.SetDNS01Provider(provider)
|
if len(dnsNameservers) > 0 && dnsNameservers[0] != "" {
|
||||||
|
a.Logf("Using DNS servers: "+strings.Join(dnsNameservers, ", "), nil)
|
||||||
|
err = client.Challenge.SetDNS01Provider(provider, dns01.AddRecursiveNameservers(dnsNameservers))
|
||||||
|
} else {
|
||||||
|
// Use default DNS-01 nameservers if dnsServers is empty
|
||||||
|
err = client.Challenge.SetDNS01Provider(provider, dns01.AddRecursiveNameservers(defaultNameservers))
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.Logf("Failed to resolve DNS01 Provider", err)
|
a.Logf("Failed to resolve DNS01 Provider", err)
|
||||||
return false, err
|
return false, err
|
||||||
@ -292,12 +323,13 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save certificate's ACME info for renew usage
|
// Save certificate's ACME info for renew usage
|
||||||
certInfo := &CertificateInfoJSON{
|
certInfo = &CertificateInfoJSON{
|
||||||
AcmeName: caName,
|
AcmeName: caName,
|
||||||
AcmeUrl: caUrl,
|
AcmeUrl: caUrl,
|
||||||
SkipTLS: skipTLS,
|
SkipTLS: skipTLS,
|
||||||
UseDNS: useDNS,
|
UseDNS: useDNS,
|
||||||
PropTimeout: propagationTimeout,
|
PropTimeout: propagationTimeout,
|
||||||
|
DNSServers: dnsNameservers,
|
||||||
}
|
}
|
||||||
|
|
||||||
certInfoBytes, err := json.Marshal(certInfo)
|
certInfoBytes, err := json.Marshal(certInfo)
|
||||||
@ -484,7 +516,21 @@ func (a *ACMEHandler) HandleRenewCertificate(w http.ResponseWriter, r *http.Requ
|
|||||||
for _, domain := range domains {
|
for _, domain := range domains {
|
||||||
cleanedDomains = append(cleanedDomains, strings.TrimSpace(domain))
|
cleanedDomains = append(cleanedDomains, strings.TrimSpace(domain))
|
||||||
}
|
}
|
||||||
result, err := a.ObtainCert(cleanedDomains, filename, email, ca, caUrl, skipTLS, dns, propagationTimeout)
|
|
||||||
|
// Extract DNS servers from the request
|
||||||
|
var dnsServers []string
|
||||||
|
dnsServersPara, err := utils.PostPara(r, "dnsServers")
|
||||||
|
if err == nil && dnsServersPara != "" {
|
||||||
|
dnsServers = strings.Split(dnsServersPara, ",")
|
||||||
|
for i := range dnsServers {
|
||||||
|
dnsServers[i] = strings.TrimSpace(dnsServers[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert DNS servers slice to a single string
|
||||||
|
dnsServersString := strings.Join(dnsServers, ",")
|
||||||
|
|
||||||
|
result, err := a.ObtainCert(cleanedDomains, filename, email, ca, caUrl, skipTLS, dns, propagationTimeout, dnsServersString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.SendErrorResponse(w, jsonEscape(err.Error()))
|
utils.SendErrorResponse(w, jsonEscape(err.Error()))
|
||||||
return
|
return
|
||||||
@ -527,5 +573,10 @@ func LoadCertInfoJSON(filename string) (*CertificateInfoJSON, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean DNS servers
|
||||||
|
for i := range certInfo.DNSServers {
|
||||||
|
certInfo.DNSServers[i] = strings.TrimSpace(certInfo.DNSServers[i])
|
||||||
|
}
|
||||||
|
|
||||||
return certInfo, nil
|
return certInfo, nil
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ type AutoRenewConfig struct {
|
|||||||
Email string //Email for acme
|
Email string //Email for acme
|
||||||
RenewAll bool //Renew all or selective renew with the slice below
|
RenewAll bool //Renew all or selective renew with the slice below
|
||||||
FilesToRenew []string //If RenewAll is false, renew these certificate files
|
FilesToRenew []string //If RenewAll is false, renew these certificate files
|
||||||
|
DNSServers string // DNS servers
|
||||||
}
|
}
|
||||||
|
|
||||||
type AutoRenewer struct {
|
type AutoRenewer struct {
|
||||||
@ -390,7 +391,13 @@ func (a *AutoRenewer) renewExpiredDomains(certs []*ExpiredCerts) ([]string, erro
|
|||||||
certInfo.PropTimeout = 300
|
certInfo.PropTimeout = 300
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = a.AcmeHandler.ObtainCert(expiredCert.Domains, certName, a.RenewerConfig.Email, certInfo.AcmeName, certInfo.AcmeUrl, certInfo.SkipTLS, certInfo.UseDNS, certInfo.PropTimeout)
|
// Extract DNS servers from the certificate info if available
|
||||||
|
var dnsServers string
|
||||||
|
if len(certInfo.DNSServers) > 0 {
|
||||||
|
dnsServers = strings.Join(certInfo.DNSServers, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = a.AcmeHandler.ObtainCert(expiredCert.Domains, certName, a.RenewerConfig.Email, certInfo.AcmeName, certInfo.AcmeUrl, certInfo.SkipTLS, certInfo.UseDNS, certInfo.PropTimeout, dnsServers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.Logf("Renew "+fileName+"("+strings.Join(expiredCert.Domains, ",")+") failed", err)
|
a.Logf("Renew "+fileName+"("+strings.Join(expiredCert.Domains, ",")+") failed", err)
|
||||||
} else {
|
} else {
|
||||||
@ -459,12 +466,18 @@ func (a *AutoRenewer) HandleSetDNS(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dnsServers, err := utils.PostPara(r, "dnsServers")
|
||||||
|
if err != nil {
|
||||||
|
dnsServers = ""
|
||||||
|
}
|
||||||
|
|
||||||
if !a.AcmeHandler.Database.TableExists("acme") {
|
if !a.AcmeHandler.Database.TableExists("acme") {
|
||||||
a.AcmeHandler.Database.NewTable("acme")
|
a.AcmeHandler.Database.NewTable("acme")
|
||||||
}
|
}
|
||||||
|
|
||||||
a.AcmeHandler.Database.Write("acme", filename+"_dns_provider", dnsProvider)
|
a.AcmeHandler.Database.Write("acme", filename+"_dns_provider", dnsProvider)
|
||||||
a.AcmeHandler.Database.Write("acme", filename+"_dns_credentials", dnsCredentials)
|
a.AcmeHandler.Database.Write("acme", filename+"_dns_credentials", dnsCredentials)
|
||||||
|
a.AcmeHandler.Database.Write("acme", filename+"_dns_servers", dnsServers)
|
||||||
|
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
|
|
||||||
|
@ -161,6 +161,11 @@
|
|||||||
</div>
|
</div>
|
||||||
-->
|
-->
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field dnsChallengeOnly" style="display:none;">
|
||||||
|
<label>Domain Name Server (optional)</label>
|
||||||
|
<input id="dnsInput" type="text" placeholder="ns.example.com">
|
||||||
|
<small>If you have more than one DNS server, enter them separated by commas (e.g. ns1.example.com,ns2.example.com)</small>
|
||||||
|
</div>
|
||||||
<div class="field" id="caInput" style="display:none;">
|
<div class="field" id="caInput" style="display:none;">
|
||||||
<label>ACME Server URL</label>
|
<label>ACME Server URL</label>
|
||||||
<input id="caURL" type="text" placeholder="https://example.com/acme/dictionary">
|
<input id="caURL" type="text" placeholder="https://example.com/acme/dictionary">
|
||||||
@ -725,8 +730,7 @@
|
|||||||
if (callback != undefined){callback(false);}
|
if (callback != undefined){callback(false);}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var ca = $("#ca").dropdown("get value");
|
var ca = $("#ca").dropdown("get value");
|
||||||
var caURL = "";
|
var caURL = "";
|
||||||
if (ca == "Custom ACME Server") {
|
if (ca == "Custom ACME Server") {
|
||||||
@ -734,9 +738,9 @@
|
|||||||
caURL = $("#caURL").val();
|
caURL = $("#caURL").val();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var dns = $("#useDnsChallenge")[0].checked;
|
var dns = $("#useDnsChallenge")[0].checked;
|
||||||
var skipTLSValue = $("#skipTLSCheckbox")[0].checked;
|
var skipTLSValue = $("#skipTLSCheckbox")[0].checked;
|
||||||
|
var dnsServers = $("#dnsInput").val(); // Erfassen der DNS-Server
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/api/acme/obtainCert",
|
url: "/api/acme/obtainCert",
|
||||||
@ -749,6 +753,7 @@
|
|||||||
caURL: caURL,
|
caURL: caURL,
|
||||||
skipTLS: skipTLSValue,
|
skipTLS: skipTLSValue,
|
||||||
dns: dns,
|
dns: dns,
|
||||||
|
dnsServers: dnsServers // DNS-Server in die Anfrage einfügen
|
||||||
},
|
},
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
$("#obtainButton").removeClass("loading").removeClass("disabled");
|
$("#obtainButton").removeClass("loading").removeClass("disabled");
|
||||||
@ -761,7 +766,6 @@
|
|||||||
console.log("Certificate renewed successfully");
|
console.log("Certificate renewed successfully");
|
||||||
// Show success message
|
// Show success message
|
||||||
parent.msgbox("Certificate renewed successfully");
|
parent.msgbox("Certificate renewed successfully");
|
||||||
|
|
||||||
// Renew the parent certificate list
|
// Renew the parent certificate list
|
||||||
parent.initManagedDomainCertificateList();
|
parent.initManagedDomainCertificateList();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user