SSL exception: “No subject alternative names matching IP address …” & “No name

  • Post author:
  • Post category:其他


When you want to establish an SSL connection like this;


URL url = new URL("https://localhost:9443/soap_rpc");

You may get an exception like this;



javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching localhost found





at com.sun.net.ssl.internal.ssl.Alerts.getSSLException


(


Alerts.java:


174


)





at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal


(


SSLSocketImpl.java:


1591


)





at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE


(


Handshaker.java:


187


)





at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE


(


Handshaker.java:


181


)





at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate


(


ClientHandshaker.java:


975


)





at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage


(


ClientHandshaker.java:


123


)





at com.sun.net.ssl.internal.ssl.Handshaker.processLoop


(


Handshaker.java:


516


)





at com.sun.net.ssl.internal.ssl.Handshaker.process_record


(


Handshaker.java:


454


)





at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord


(


SSLSocketImpl.java:


884


)





at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake


(


SSLSocketImpl.java:


1096


)





at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake


(


SSLSocketImpl.java:


1123


)





at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake


(


SSLSocketImpl.java:


1107


)





at sun.net.www.protocol.https.HttpsClient.afterConnect


(


HttpsClient.java:


405


)





at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect


(


AbstractDelegateHttpsURLConnection.java:


166


)





at sun.net.www.protocol.http.HttpURLConnection.getOutputStream


(


HttpURLConnection.java:


832


)





at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream


(


HttpsURLConnectionImpl.java:


230


)





at SSLPost.test


(


SSLPost.java:


74


)





at SSLPost.<init>


(


SSLPost.java:


29


)





at SSLPost.main


(


SSLPost.java:


98


)



Caused by: java.security.cert.CertificateException: No name matching localhost found





at sun.security.util.HostnameChecker.matchDNS


(


HostnameChecker.java:


210


)





at sun.security.util.HostnameChecker.match


(


HostnameChecker.java:


77


)





at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkIdentity


(


X509TrustManagerImpl.java:


264


)





at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted


(


X509TrustManagerImpl.java:


250


)





at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate


(


ClientHandshaker.java:


954


)





...


14


more

But, you have installed the server certificate, generated keystore and all work fine. So, what may be the problem?

Let’s come to the solution;

While making an SSL connection,

HttpsClient

steps in and does basic server authentication to protect against URL spoofing which includes verifying that the name of the server is found in the certificate.

HttpsClient#checkURLSpoofing

method checks server identity according to “RFC 2818: HTTP over TLS” – “Section 3.1 Server Identity”.

HttpsClient basically uses

HostNameChecker

first to check the hostname against the names specified in the certificate. Then, if it fails, HostNameVerifier’s turn comes and it’s used to verify the host name. As mentioned above, while not overridden, SUN’s default behaviour is returning

false

for this verification. This means, if your HostNameChecker fails, you will get one of the exceptions written in the title according to your URL’s hostname type.

So, what can be done to “not-fail” HostNameChecker?


HostNameChecker#match

method’s implementation is like below;




sun.security.util.HostNameChecker





public




void



match


(


String hostName, X509Certificate x509certificate


)



throws



CertificateException


{







if



(


isIpAddress


(


hostName


)) {






matchIP


(


hostName, x509certificate


)


;





}



else



{






matchDNS


(


hostName, x509certificate


)


;





}



}

If the incoming hostname is IP, (by matchIP method), it will be searched in available subject alternative names and throw CertificateException(“No subject alternative names matching IP address …”) if no matching ip value found.

On the other hand, if the incoming hostname is DNS, (by matchDNS method), it will be searched in available subject alternative names but, different from IP matching algorithm, DNS matching will compare the hostname with the CommonName value from certificate if available. If neither matches with the hostname, a CertificateException(“No name matching … found”) will be thrown.

What we can conclude from these details is;

  • if you’d like to connect via using IP as hostname; your certificate should include that ip value as a subject alternative name value (of type IPAddress : key=7).
  • if you’d like to connect via using DNS as hostname; your certificate should either include that DNS name as a subject alternative name value (of type DNS : key=2) or as a CommonName(CN) value.

Hope it helps…



版权声明:本文为iteye_4120原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。