Add ACME EAB support

This commit is contained in:
世界 2022-08-24 17:04:15 +08:00
parent ad90ddd327
commit 71dac85600
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
5 changed files with 59 additions and 25 deletions

View file

@ -21,7 +21,11 @@
"disable_http_challenge": false, "disable_http_challenge": false,
"disable_tls_alpn_challenge": false, "disable_tls_alpn_challenge": false,
"alternative_http_port": 0, "alternative_http_port": 0,
"alternative_tls_port": 0 "alternative_tls_port": 0,
"external_account": {
"key_id": "",
"mac_key": ""
}
} }
} }
``` ```
@ -206,3 +210,22 @@ succeed.
### Reload ### Reload
For server configuration, certificate and key will be automatically reloaded if modified. 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.

2
go.mod
View file

@ -15,6 +15,7 @@ require (
github.com/gorilla/websocket v1.5.0 github.com/gorilla/websocket v1.5.0
github.com/hashicorp/yamux v0.1.1 github.com/hashicorp/yamux v0.1.1
github.com/logrusorgru/aurora v2.0.3+incompatible 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/oschwald/maxminddb-golang v1.10.0
github.com/pires/go-proxyproto v0.6.2 github.com/pires/go-proxyproto v0.6.2
github.com/sagernet/certmagic v0.0.0-20220819042630-4a57f8b6853a 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/qpack v0.2.1 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.2 // 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/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/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect github.com/onsi/ginkgo v1.16.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect

View file

@ -11,6 +11,8 @@ import (
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/option" "github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions" E "github.com/sagernet/sing/common/exceptions"
"github.com/mholt/acmez/acme"
) )
type acmeWrapper struct { type acmeWrapper struct {
@ -53,17 +55,19 @@ func startACME(ctx context.Context, options option.InboundACMEOptions) (*tls.Con
DefaultServerName: options.DefaultServerName, DefaultServerName: options.DefaultServerName,
Storage: storage, Storage: storage,
} }
config.Issuers = []certmagic.Issuer{ acmeConfig := certmagic.ACMEIssuer{
certmagic.NewACMEIssuer(config, certmagic.ACMEIssuer{ CA: acmeServer,
CA: acmeServer, Email: options.Email,
Email: options.Email, Agreed: true,
Agreed: true, DisableHTTPChallenge: options.DisableHTTPChallenge,
DisableHTTPChallenge: options.DisableHTTPChallenge, DisableTLSALPNChallenge: options.DisableTLSALPNChallenge,
DisableTLSALPNChallenge: options.DisableTLSALPNChallenge, AltHTTPPort: int(options.AlternativeHTTPPort),
AltHTTPPort: int(options.AlternativeHTTPPort), AltTLSALPNPort: int(options.AlternativeTLSPort),
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{ config = certmagic.New(certmagic.NewCache(certmagic.CacheOptions{
GetConfigForCert: func(certificate certmagic.Certificate) (*certmagic.Config, error) { GetConfigForCert: func(certificate certmagic.Certificate) (*certmagic.Config, error) {
return config, nil return config, nil

View file

@ -20,18 +20,6 @@ type InboundTLSOptions struct {
ACME *InboundACMEOptions `json:"acme,omitempty"` 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 { type OutboundTLSOptions struct {
Enabled bool `json:"enabled,omitempty"` Enabled bool `json:"enabled,omitempty"`
DisableSNI bool `json:"disable_sni,omitempty"` DisableSNI bool `json:"disable_sni,omitempty"`

19
option/tls_acme.go Normal file
View file

@ -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"`
}