From afc6b1ba767c981508d7eeae5d4beb3b4c44c177 Mon Sep 17 00:00:00 2001 From: Maksim Kazantsev Date: Mon, 20 Jul 2026 13:46:32 +0300 Subject: [PATCH] dnsforward: add common name fallback; home: imp onGetCertificate; --- internal/dnsforward/config.go | 11 ++++++++++- internal/dnsforward/dnsforward.go | 2 +- internal/home/tls.go | 8 +++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/internal/dnsforward/config.go b/internal/dnsforward/config.go index 6259015b2..100992717 100644 --- a/internal/dnsforward/config.go +++ b/internal/dnsforward/config.go @@ -768,12 +768,21 @@ func (s *Server) replaceGetCertificate(orig *tls.Config) { origGetCert := orig.GetCertificate orig.GetCertificate = func(chi *tls.ClientHelloInfo) (cert *tls.Certificate, err error) { + // Ignore the error from the original GetCertificate, since the current + // implementation of the method always returns nil. cert, _ = origGetCert(chi) if cert == nil || cert.Leaf == nil { return nil, errors.Error("tls certificate is not set") } - if !anyNameMatches(cert.Leaf.DNSNames, chi.ServerName) { + var dnsNames []string + if len(cert.Leaf.DNSNames) == 0 { + dnsNames = []string{cert.Leaf.Subject.CommonName} + } else { + dnsNames = cert.Leaf.DNSNames + } + + if !anyNameMatches(dnsNames, chi.ServerName) { s.logger.Warn("unknown sni in client hello", "server_name", chi.ServerName) return nil, fmt.Errorf("invalid sni: %s", chi.ServerName) diff --git a/internal/dnsforward/dnsforward.go b/internal/dnsforward/dnsforward.go index 0063f9009..e396e0c50 100644 --- a/internal/dnsforward/dnsforward.go +++ b/internal/dnsforward/dnsforward.go @@ -480,7 +480,7 @@ func (s *Server) startLocked(ctx context.Context) error { return err } -// Prepare initialises parameters of s using data from conf. It can be called +// Prepare initializes parameters of s using data from conf. It can be called // from outside of the package and without acquired s.serverLock only while the // initialization. conf must be non-nil and valid. func (s *Server) Prepare(ctx context.Context, conf *ServerConfig) (err error) { diff --git a/internal/home/tls.go b/internal/home/tls.go index 252a0f7ad..8fad020e4 100644 --- a/internal/home/tls.go +++ b/internal/home/tls.go @@ -41,7 +41,8 @@ type tlsManager struct { // certLastMod is the last modification time of the certificate file. certLastMod time.Time - // tlsCert is a current TLS certificate. It may be nil. + // tlsCert is the current TLS certificate. tlsCert must not be stored in + // [tls.Config.Certificates], as it violates its documentation. // // TODO(m.kazantsev): Consider a better approach to store the certificate. tlsCert *tls.Certificate @@ -885,6 +886,11 @@ func (m *tlsManager) onGetCertificate(chi *tls.ClientHelloInfo) (cert *tls.Certi return nil, nil } + err = chi.SupportsCertificate(m.tlsCert) + if err != nil { + return nil, fmt.Errorf("client hello does not support certificate: %w", err) + } + tlsCert := *m.tlsCert return &tlsCert, nil