dnsforward: add common name fallback; home: imp onGetCertificate;

This commit is contained in:
Maksim Kazantsev 2026-07-20 13:46:32 +03:00
parent 30b71c50ce
commit afc6b1ba76
3 changed files with 18 additions and 3 deletions

View file

@ -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)

View file

@ -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) {

View file

@ -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