github.com/sagernet/sing-box@v1.2.7/common/tls/acme.go (about) 1 //go:build with_acme 2 3 package tls 4 5 import ( 6 "context" 7 "crypto/tls" 8 "os" 9 "strings" 10 11 "github.com/sagernet/sing-box/adapter" 12 "github.com/sagernet/sing-box/option" 13 E "github.com/sagernet/sing/common/exceptions" 14 15 "github.com/caddyserver/certmagic" 16 "github.com/mholt/acmez/acme" 17 "go.uber.org/zap" 18 "go.uber.org/zap/zapcore" 19 ) 20 21 type acmeWrapper struct { 22 ctx context.Context 23 cfg *certmagic.Config 24 domain []string 25 } 26 27 func (w *acmeWrapper) Start() error { 28 return w.cfg.ManageSync(w.ctx, w.domain) 29 } 30 31 func (w *acmeWrapper) Close() error { 32 w.cfg.Unmanage(w.domain) 33 return nil 34 } 35 36 func startACME(ctx context.Context, options option.InboundACMEOptions) (*tls.Config, adapter.Service, error) { 37 var acmeServer string 38 switch options.Provider { 39 case "", "letsencrypt": 40 acmeServer = certmagic.LetsEncryptProductionCA 41 case "zerossl": 42 acmeServer = certmagic.ZeroSSLProductionCA 43 default: 44 if !strings.HasPrefix(options.Provider, "https://") { 45 return nil, nil, E.New("unsupported acme provider: " + options.Provider) 46 } 47 acmeServer = options.Provider 48 } 49 var storage certmagic.Storage 50 if options.DataDirectory != "" { 51 storage = &certmagic.FileStorage{ 52 Path: options.DataDirectory, 53 } 54 } else { 55 storage = certmagic.Default.Storage 56 } 57 config := &certmagic.Config{ 58 DefaultServerName: options.DefaultServerName, 59 Storage: storage, 60 Logger: zap.New(zapcore.NewCore( 61 zapcore.NewConsoleEncoder(zap.NewProductionEncoderConfig()), 62 os.Stderr, 63 zap.InfoLevel, 64 )), 65 } 66 acmeConfig := certmagic.ACMEIssuer{ 67 CA: acmeServer, 68 Email: options.Email, 69 Agreed: true, 70 DisableHTTPChallenge: options.DisableHTTPChallenge, 71 DisableTLSALPNChallenge: options.DisableTLSALPNChallenge, 72 AltHTTPPort: int(options.AlternativeHTTPPort), 73 AltTLSALPNPort: int(options.AlternativeTLSPort), 74 Logger: config.Logger, 75 } 76 if options.ExternalAccount != nil && options.ExternalAccount.KeyID != "" { 77 acmeConfig.ExternalAccount = (*acme.EAB)(options.ExternalAccount) 78 } 79 config.Issuers = []certmagic.Issuer{certmagic.NewACMEIssuer(config, acmeConfig)} 80 config = certmagic.New(certmagic.NewCache(certmagic.CacheOptions{ 81 GetConfigForCert: func(certificate certmagic.Certificate) (*certmagic.Config, error) { 82 return config, nil 83 }, 84 }), *config) 85 return config.TLSConfig(), &acmeWrapper{ctx, config, options.Domain}, nil 86 }