diff --git a/docs/configuration/shared/tls.md b/docs/configuration/shared/tls.md index 42f1f7da..666c61df 100644 --- a/docs/configuration/shared/tls.md +++ b/docs/configuration/shared/tls.md @@ -21,7 +21,11 @@ "disable_http_challenge": false, "disable_tls_alpn_challenge": false, "alternative_http_port": 0, - "alternative_tls_port": 0 + "alternative_tls_port": 0, + "external_account": { + "key_id": "", + "mac_key": "" + } } } ``` @@ -205,4 +209,23 @@ succeed. ### Reload -For server configuration, certificate and key will be automatically reloaded if modified. \ No newline at end of file +For server configuration, certificate and key will be automatically reloaded if modified. + +#### external_account + +EAB (External Account Binding) contains information necessary to bind or map an ACME account to some other account known +by the CA. + +External account bindings are "used to associate an ACME account with an existing account in a non-ACME system, such as +a CA customer database. + +To enable ACME account binding, the CA operating the ACME server needs to provide the ACME client with a MAC key and a +key identifier, using some mechanism outside of ACME. ยง7.3.4 + +#### external_account.key_id + +The key identifier. + +#### external_account.mac_key + +The MAC key. \ No newline at end of file diff --git a/go.mod b/go.mod index ba387108..06aa240e 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/gorilla/websocket v1.5.0 github.com/hashicorp/yamux v0.1.1 github.com/logrusorgru/aurora v2.0.3+incompatible + github.com/mholt/acmez v1.0.4 github.com/oschwald/maxminddb-golang v1.10.0 github.com/pires/go-proxyproto v0.6.2 github.com/sagernet/certmagic v0.0.0-20220819042630-4a57f8b6853a @@ -51,7 +52,6 @@ require ( github.com/marten-seemann/qpack v0.2.1 // indirect github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect - github.com/mholt/acmez v1.0.4 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/onsi/ginkgo v1.16.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/inbound/tls_acme.go b/inbound/tls_acme.go index 19667a1b..0e9d32cf 100644 --- a/inbound/tls_acme.go +++ b/inbound/tls_acme.go @@ -11,6 +11,8 @@ import ( "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/option" E "github.com/sagernet/sing/common/exceptions" + + "github.com/mholt/acmez/acme" ) type acmeWrapper struct { @@ -53,17 +55,19 @@ func startACME(ctx context.Context, options option.InboundACMEOptions) (*tls.Con DefaultServerName: options.DefaultServerName, Storage: storage, } - config.Issuers = []certmagic.Issuer{ - certmagic.NewACMEIssuer(config, certmagic.ACMEIssuer{ - CA: acmeServer, - Email: options.Email, - Agreed: true, - DisableHTTPChallenge: options.DisableHTTPChallenge, - DisableTLSALPNChallenge: options.DisableTLSALPNChallenge, - AltHTTPPort: int(options.AlternativeHTTPPort), - AltTLSALPNPort: int(options.AlternativeTLSPort), - }), + acmeConfig := certmagic.ACMEIssuer{ + CA: acmeServer, + Email: options.Email, + Agreed: true, + DisableHTTPChallenge: options.DisableHTTPChallenge, + DisableTLSALPNChallenge: options.DisableTLSALPNChallenge, + AltHTTPPort: int(options.AlternativeHTTPPort), + AltTLSALPNPort: int(options.AlternativeTLSPort), } + if options.ExternalAccount != nil { + acmeConfig.ExternalAccount = (*acme.EAB)(options.ExternalAccount) + } + config.Issuers = []certmagic.Issuer{certmagic.NewACMEIssuer(config, acmeConfig)} config = certmagic.New(certmagic.NewCache(certmagic.CacheOptions{ GetConfigForCert: func(certificate certmagic.Certificate) (*certmagic.Config, error) { return config, nil diff --git a/option/tls.go b/option/tls.go index b403a2dc..4ee64f59 100644 --- a/option/tls.go +++ b/option/tls.go @@ -20,18 +20,6 @@ type InboundTLSOptions struct { ACME *InboundACMEOptions `json:"acme,omitempty"` } -type InboundACMEOptions struct { - Domain Listable[string] `json:"domain,omitempty"` - DataDirectory string `json:"data_directory,omitempty"` - DefaultServerName string `json:"default_server_name,omitempty"` - Email string `json:"email,omitempty"` - Provider string `json:"provider,omitempty"` - DisableHTTPChallenge bool `json:"disable_http_challenge,omitempty"` - DisableTLSALPNChallenge bool `json:"disable_tls_alpn_challenge,omitempty"` - AlternativeHTTPPort uint16 `json:"alternative_http_port,omitempty"` - AlternativeTLSPort uint16 `json:"alternative_tls_port,omitempty"` -} - type OutboundTLSOptions struct { Enabled bool `json:"enabled,omitempty"` DisableSNI bool `json:"disable_sni,omitempty"` diff --git a/option/tls_acme.go b/option/tls_acme.go new file mode 100644 index 00000000..c9c1e0a5 --- /dev/null +++ b/option/tls_acme.go @@ -0,0 +1,19 @@ +package option + +type InboundACMEOptions struct { + Domain Listable[string] `json:"domain,omitempty"` + DataDirectory string `json:"data_directory,omitempty"` + DefaultServerName string `json:"default_server_name,omitempty"` + Email string `json:"email,omitempty"` + Provider string `json:"provider,omitempty"` + DisableHTTPChallenge bool `json:"disable_http_challenge,omitempty"` + DisableTLSALPNChallenge bool `json:"disable_tls_alpn_challenge,omitempty"` + AlternativeHTTPPort uint16 `json:"alternative_http_port,omitempty"` + AlternativeTLSPort uint16 `json:"alternative_tls_port,omitempty"` + ExternalAccount *ACMEExternalAccountOptions `json:"external_account,omitempty"` +} + +type ACMEExternalAccountOptions struct { + KeyID string `json:"key_id,omitempty"` + MACKey string `json:"mac_key,omitempty"` +}