github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/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/inazumav/sing-box/adapter" 12 "github.com/inazumav/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 cache *certmagic.Cache 25 domain []string 26 } 27 28 func (w *acmeWrapper) Start() error { 29 return w.cfg.ManageSync(w.ctx, w.domain) 30 } 31 32 func (w *acmeWrapper) Close() error { 33 w.cache.Stop() 34 return nil 35 } 36 37 func startACME(ctx context.Context, options option.InboundACMEOptions) (*tls.Config, adapter.Service, error) { 38 var acmeServer string 39 switch options.Provider { 40 case "", "letsencrypt": 41 acmeServer = certmagic.LetsEncryptProductionCA 42 case "zerossl": 43 acmeServer = certmagic.ZeroSSLProductionCA 44 default: 45 if !strings.HasPrefix(options.Provider, "https://") { 46 return nil, nil, E.New("unsupported acme provider: " + options.Provider) 47 } 48 acmeServer = options.Provider 49 } 50 var storage certmagic.Storage 51 if options.DataDirectory != "" { 52 storage = &certmagic.FileStorage{ 53 Path: options.DataDirectory, 54 } 55 } else { 56 storage = certmagic.Default.Storage 57 } 58 config := &certmagic.Config{ 59 DefaultServerName: options.DefaultServerName, 60 Storage: storage, 61 Logger: zap.New(zapcore.NewCore( 62 zapcore.NewConsoleEncoder(zap.NewProductionEncoderConfig()), 63 os.Stderr, 64 zap.InfoLevel, 65 )), 66 } 67 acmeConfig := certmagic.ACMEIssuer{ 68 CA: acmeServer, 69 Email: options.Email, 70 Agreed: true, 71 DisableHTTPChallenge: options.DisableHTTPChallenge, 72 DisableTLSALPNChallenge: options.DisableTLSALPNChallenge, 73 AltHTTPPort: int(options.AlternativeHTTPPort), 74 AltTLSALPNPort: int(options.AlternativeTLSPort), 75 Logger: config.Logger, 76 } 77 if options.ExternalAccount != nil && options.ExternalAccount.KeyID != "" { 78 acmeConfig.ExternalAccount = (*acme.EAB)(options.ExternalAccount) 79 } 80 config.Issuers = []certmagic.Issuer{certmagic.NewACMEIssuer(config, acmeConfig)} 81 cache := certmagic.NewCache(certmagic.CacheOptions{ 82 GetConfigForCert: func(certificate certmagic.Certificate) (*certmagic.Config, error) { 83 return config, nil 84 }, 85 }) 86 config = certmagic.New(cache, *config) 87 return config.TLSConfig(), &acmeWrapper{ctx: ctx, cfg: config, cache: cache, domain: options.Domain}, nil 88 }