{"record":{"id":"fab9f60a8d5f6365","repo":"alibaba/canal","slug":"server-certificate-identity-check-failed-the-cert","errorCode":null,"errorMessage":"Server certificate identity check failed. The certificate Common Name '{}' does not match with '{}'.","messagePattern":"Server certificate identity check failed\\. The certificate Common Name '(.+?)' does not match with '(.+?)'\\.","errorType":"exception","errorClass":"CertificateException","httpStatus":null,"severity":"critical","filePath":"driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/socket/BioSocketChannelPool.java","lineNumber":307,"sourceCode":"                        String dn = certificate.getSubjectX500Principal().getName(X500Principal.RFC2253);\n                        String cn = null;\n                        try {\n                            LdapName ldapDN = new LdapName(dn);\n                            for (Rdn rdn : ldapDN.getRdns()) {\n                                if (rdn.getType().equalsIgnoreCase(\"CN\")) {\n                                    cn = rdn.getValue().toString();\n                                    break;\n                                }\n                            }\n                        } catch (InvalidNameException e) {\n                            throw new CertificateException(\n                                \"Failed to retrieve the Common Name (CN) from the server certificate.\");\n                        }\n                        expectHostNames.add(cn);\n                    }\n\n                    if (!expectHostNames.contains(this.hostName)) {\n                        throw new CertificateException(\n                            \"Server certificate identity check failed. The certificate Common Name \"\n                                                       + expectHostNames.stream()\n                                                           .map(h -> \"'\" + h + \"'\")\n                                                           .collect(Collectors.joining(\", \"))\n                                                       + \" does not match with '\" + this.hostName + \"'.\");\n                    }\n\n                }\n            }\n        }\n\n        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {\n            this.origTm.checkClientTrusted(chain, authType);\n        }\n    }\n\n}\n","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/socket/BioSocketChannelPool.java#L289-L325","documentation":"Thrown during VERIFY_IDENTITY hostname verification when none of the certificates' CN values in the chain equals the hostName the client connected to (socket.getInetAddress().getHostName()). The message lists the CNs found and the expected host. This is the classic TLS hostname-mismatch failure for MySQL SSL.","triggerScenarios":"Connecting to a MySQL host whose certificate CN does not match the hostname/IP the client used (e.g. connecting by IP while the cert CN is a DNS name, or to a replica whose cert was minted for the primary's name). Triggered only in VERIFY_IDENTITY mode.","commonSituations":"Connecting by IP address but cert CN is a domain; cert issued for a different cluster node; wildcard/SAN not honored (parser only checks CN); misconfigured canal.instance.master.address that does not match the cert; copied a cert across failover replicas without reissuing.","solutions":["Connect using the exact hostname that appears in the certificate CN.","Reissue the server certificate so its CN matches the address clients use (and include SANs).","Ensure canals.master.address / jdbc URL host matches the cert CN.","If hostname match is not enforceable, downgrade to SslMode.VERIFY_CA (chain trusted, no hostname check).","Add the hostname to Subject Alternative Names if the cert supports SAN."],"exampleFix":"# before\n# canal.instance.master.address = 10.0.0.5:3306\n# cert CN = mysql.internal.example.com -> mismatch\n\n# after (option A: connect by the cert name)\ncanal.instance.master.address = mysql.internal.example.com:3306\n# option B: reissue cert with SAN covering the IP\n# [alt_names]\n# IP.1 = 10.0.0.5","handlingStrategy":"validation","validationCode":"// Ensure the configured host matches a CN in the cert before enabling VERIFY_IDENTITY\nString host = addressHost; // what the client connects to\nSet<String> cns = extractCNs(serverCert);\nif (!cns.contains(host)) { /* reissue cert or connect by the cert CN, or use VERIFY_CA */ }","typeGuard":"public static boolean hostMatchesCert(String host, X509Certificate cert) {\n    try {\n        String dn = cert.getSubjectX500Principal().getName(X500Principal.RFC2253);\n        for (javax.naming.ldap.Rdn rdn : new javax.naming.ldap.LdapName(dn).getRdns()) {\n            if (rdn.getType().equalsIgnoreCase(\"CN\") && host.equals(rdn.getValue().toString())) return true;\n        }\n    } catch (Exception ignore) {}\n    return false;\n}","tryCatchPattern":"try {\n    sslSocket.startHandshake();\n} catch (javax.net.ssl.SSLHandshakeException e) {\n    Throwable c = e.getCause();\n    if (c instanceof java.security.cert.CertificateException\n        && c.getMessage().contains(\"identity check failed\")) {\n        // fix canal.instance.master.address or reissue cert; or use VERIFY_CA\n    }\n    throw e;\n}","preventionTips":["Connect using the exact hostname in the certificate CN.","Reissue certs so the CN matches the address clients use (include SANs).","Fall back to VERIFY_CA when hostname matching is not enforceable."],"tags":["network","ssl","tls","certificate","hostname","security","config"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}