acme.go 2.1 KB

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