diff --git a/common/tls/acme.go b/common/tls/acme.go index b8aef70f..c96e002c 100644 --- a/common/tls/acme.go +++ b/common/tls/acme.go @@ -14,6 +14,7 @@ import ( "github.com/sagernet/sing/common/logger" "github.com/caddyserver/certmagic" + "github.com/libdns/acmedns" "github.com/libdns/alidns" "github.com/libdns/cloudflare" "github.com/mholt/acmez/v3/acme" @@ -126,6 +127,13 @@ func startACME(ctx context.Context, logger logger.Logger, options option.Inbound APIToken: dnsOptions.CloudflareOptions.APIToken, ZoneToken: dnsOptions.CloudflareOptions.ZoneToken, } + case C.DNSProviderACMEDNS: + solver.DNSProvider = &acmedns.Provider{ + Username: dnsOptions.ACMEDNSOptions.Username, + Password: dnsOptions.ACMEDNSOptions.Password, + Subdomain: dnsOptions.ACMEDNSOptions.Subdomain, + ServerURL: dnsOptions.ACMEDNSOptions.ServerURL, + } default: return nil, nil, E.New("unsupported ACME DNS01 provider type: " + dnsOptions.Provider) } diff --git a/constant/dns.go b/constant/dns.go index 99e1ec0e..15d6096c 100644 --- a/constant/dns.go +++ b/constant/dns.go @@ -33,4 +33,5 @@ const ( const ( DNSProviderAliDNS = "alidns" DNSProviderCloudflare = "cloudflare" + DNSProviderACMEDNS = "acmedns" ) diff --git a/docs/configuration/shared/dns01_challenge.md b/docs/configuration/shared/dns01_challenge.md index 904803e6..8bdbfc97 100644 --- a/docs/configuration/shared/dns01_challenge.md +++ b/docs/configuration/shared/dns01_challenge.md @@ -5,7 +5,8 @@ icon: material/new-box !!! quote "Changes in sing-box 1.13.0" :material-plus: [alidns.security_token](#security_token) - :material-plus: [cloudflare.zone_token](#zone_token) + :material-plus: [cloudflare.zone_token](#zone_token) + :material-plus: [acmedns](#acmedns) ### Structure @@ -54,3 +55,19 @@ The Security Token for STS temporary credentials. Optional API token with `Zone:Read` permission. When provided, allows `api_token` to be scoped to a single zone. + +#### ACME-DNS + +!!! question "Since sing-box 1.13.0" + +```json +{ + "provider": "acmedns", + "username": "", + "password": "", + "subdomain": "", + "server_url": "" +} +``` + +See [ACME-DNS](https://github.com/joohoi/acme-dns) for details. diff --git a/docs/configuration/shared/dns01_challenge.zh.md b/docs/configuration/shared/dns01_challenge.zh.md index 7fb89c11..e6919338 100644 --- a/docs/configuration/shared/dns01_challenge.zh.md +++ b/docs/configuration/shared/dns01_challenge.zh.md @@ -5,7 +5,8 @@ icon: material/new-box !!! quote "sing-box 1.13.0 中的更改" :material-plus: [alidns.security_token](#security_token) - :material-plus: [cloudflare.zone_token](#zone_token) + :material-plus: [cloudflare.zone_token](#zone_token) + :material-plus: [acmedns](#acmedns) ### 结构 @@ -54,3 +55,19 @@ icon: material/new-box 具有 `Zone:Read` 权限的可选 API 令牌。 提供后可将 `api_token` 限定到单个区域。 + +#### ACME-DNS + +!!! question "自 sing-box 1.13.0 起" + +```json +{ + "provider": "acmedns", + "username": "", + "password": "", + "subdomain": "", + "server_url": "" +} +``` + +参阅 [ACME-DNS](https://github.com/joohoi/acme-dns)。 diff --git a/go.mod b/go.mod index 942b91b1..91c529ec 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/gofrs/uuid/v5 v5.4.0 github.com/insomniacslk/dhcp v0.0.0-20251020182700-175e84fbb167 github.com/keybase/go-keychain v0.0.1 + github.com/libdns/acmedns v0.5.0 github.com/libdns/alidns v1.0.6-beta.3 github.com/libdns/cloudflare v0.2.2 github.com/logrusorgru/aurora v2.0.3+incompatible diff --git a/go.sum b/go.sum index c1a4b8c7..b2c41002 100644 --- a/go.sum +++ b/go.sum @@ -102,6 +102,8 @@ github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zt github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/libdns/acmedns v0.5.0 h1:5pRtmUj4Lb/QkNJSl1xgOGBUJTWW7RjpNaIhjpDXjPE= +github.com/libdns/acmedns v0.5.0/go.mod h1:X7UAFP1Ep9NpTwWpVlrZzJLR7epynAy0wrIxSPFgKjQ= github.com/libdns/alidns v1.0.6-beta.3 h1:KAmb7FQ1tRzKsaAUGa7ZpGKAMRANwg7+1c7tUbSELq8= github.com/libdns/alidns v1.0.6-beta.3/go.mod h1:RECwyQ88e9VqQVtSrvX76o1ux3gQUKGzMgxICi+u7Ec= github.com/libdns/cloudflare v0.2.2 h1:XWHv+C1dDcApqazlh08Q6pjytYLgR2a+Y3xrXFu0vsI= diff --git a/option/tls_acme.go b/option/tls_acme.go index 1857c747..6dd8fa70 100644 --- a/option/tls_acme.go +++ b/option/tls_acme.go @@ -31,6 +31,7 @@ type _ACMEDNS01ChallengeOptions struct { Provider string `json:"provider,omitempty"` AliDNSOptions ACMEDNS01AliDNSOptions `json:"-"` CloudflareOptions ACMEDNS01CloudflareOptions `json:"-"` + ACMEDNSOptions ACMEDNS01ACMEDNSOptions `json:"-"` } type ACMEDNS01ChallengeOptions _ACMEDNS01ChallengeOptions @@ -42,6 +43,8 @@ func (o ACMEDNS01ChallengeOptions) MarshalJSON() ([]byte, error) { v = o.AliDNSOptions case C.DNSProviderCloudflare: v = o.CloudflareOptions + case C.DNSProviderACMEDNS: + v = o.ACMEDNSOptions case "": return nil, E.New("missing provider type") default: @@ -61,6 +64,8 @@ func (o *ACMEDNS01ChallengeOptions) UnmarshalJSON(bytes []byte) error { v = &o.AliDNSOptions case C.DNSProviderCloudflare: v = &o.CloudflareOptions + case C.DNSProviderACMEDNS: + v = &o.ACMEDNSOptions default: return E.New("unknown provider type: " + o.Provider) } @@ -82,3 +87,10 @@ type ACMEDNS01CloudflareOptions struct { APIToken string `json:"api_token,omitempty"` ZoneToken string `json:"zone_token,omitempty"` } + +type ACMEDNS01ACMEDNSOptions struct { + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + Subdomain string `json:"subdomain,omitempty"` + ServerURL string `json:"server_url,omitempty"` +}