SSLPeerUnverifiedException - Certificate for <> doesn't match common name of the certificate subject

Barathi picture Barathi · Oct 27, 2017 · Viewed 9.8k times · Source

We got the following exception when we try to access secure https REST point from zuul.

2017-10-27 08:26:08.499 DEBUG 15708 --- [http-nio-9092-exec-1] o.a.h.c.ssl.SSLConnectionSocketFactory   : Secure session established
2017-10-27 08:26:08.500 DEBUG 15708 --- [http-nio-9092-exec-1] o.a.h.c.ssl.SSLConnectionSocketFactory   :  negotiated protocol: TLSv1.2
2017-10-27 08:26:08.500 DEBUG 15708 --- [http-nio-9092-exec-1] o.a.h.c.ssl.SSLConnectionSocketFactory   :  negotiated cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
2017-10-27 08:26:08.501 DEBUG 15708 --- [http-nio-9092-exec-1] o.a.h.c.ssl.SSLConnectionSocketFactory   :  peer principal: CN=10.xxx.xx.xx, OU=xxx, O=xxx, L=xxx, ST=xx, C=xx
2017-10-27 08:26:08.502 DEBUG 15708 --- [http-nio-9092-exec-1] o.a.h.c.ssl.SSLConnectionSocketFactory   :  issuer principal: CN=10.xxx.xx.xx, OU=xxx, O=xxx, L=xxx, ST=xx, C=xx
2017-10-27 08:26:08.516 DEBUG 15708 --- [http-nio-9092-exec-1] o.a.h.conn.ssl.DefaultHostnameVerifier   : Certificate for  doesn't match common name of the certificate subject: 10.xxx.xx.xx
javax.net.ssl.SSLPeerUnverifiedException: Certificate for  doesn't match common name of the certificate subject
    at org.apache.http.conn.ssl.DefaultHostnameVerifier.matchCN(DefaultHostnameVerifier.java:186)
    at org.apache.http.conn.ssl.DefaultHostnameVerifier.verify(DefaultHostnameVerifier.java:133)
    at org.apache.http.conn.ssl.DefaultHostnameVerifier.verify(DefaultHostnameVerifier.java:99)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.java:463)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:397)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:359)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
    at org.springframework.cloud.netflix.ribbon.apache.RibbonLoadBalancingHttpClient.execute(RibbonLoadBalancingHttpClient.java:94)
    at org.springframework.cloud.netflix.ribbon.apache.RibbonLoadBalancingHttpClient.execute(RibbonLoadBalancingHttpClient.java:43)
    at com.netflix.client.AbstractLoadBalancerAwareClient$1.call(AbstractLoadBalancerAwareClient.java:109)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:303)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:287)
    at rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:231)
    at rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:228)
    at rx.Observable.unsafeSubscribe(Observable.java:10211)
    at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.drain(OnSubscribeConcatMap.java:286)
    at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.onNext(OnSubscribeConcatMap.java:144)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:185)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180)
...

service is registered with eureka via POST request. Please find the below sample POST request.


    spring:
      application:
        name: gateway 
    server:
      port: 9092
      ssl:    
        enabled: true
        clientAuth: want
        key-store: classpath:keystore.jks
        key-store-password: password
        key-password: password   
        key-alias: xxxx
    eureka:
      instance:
        nonSecurePortEnabled: false
        securePortEnabled: true
      client:
        serviceUrl:
          defaultZone: ${EUREKA_URI:http://localhost:8761/eureka}
        registry-fetch-interval-seconds: 15
        register-with-eureka: true
        fetch-registry: true
        heartbeat-executor-thread-pool-size: 5
        eureka-service-url-poll-interval-seconds: 10
    zuul:
      prefix: /tree
      routes:
        serv:
          path: /cxf/**
          strip-prefix: false
          serviceId: serv
    ribbon:
      IsSecure: true
      IsHostnameValidationRequired: false

service is registered with eureka via POST request. Please find the below sample POST request.


    {
    "instance": {
        "hostName": "xxx",
        "app": "appname",
        "vipAddress": "appname",
        "secureVipAddress": "appname",
        "ipAddr": "10.xxx.xx.xxx",
        "status": "UP",
        "port": {"$": "8181", "@enabled": "true"},
        "securePort": {"$": "8443", "@enabled": "true"},
        "healthCheckUrl": "http://localhost:8000/cat",
        "statusPageUrl": "http://localhost:8000/cat",
        "homePageUrl": "http://localhost:8000/cat",
        "dataCenterInfo": {
            "@class": "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo", 
            "name": "MyOwn"
        }
    }

if I replace serviceId with the corresponding url in above zuul configuration, it works fine.

keystore.jks has been under src/main/resources. Also, imported keystore entry into certificate under $JDK_HOME/jre/lib/security/cacerts. Are we missing any other configuration?

NOTE: REST endpoint is an OSGI service. spring boot version: v1.5.7.RELEASE We use embedded tomcat.

Answer

Barathi picture Barathi · Dec 13, 2017

The reason for the above issue is the certificate doesn't contain the field "SubjectAlternativeName". After creating certificate with field "SubjectAlternativeName" which in turn includes CN(Common Name) and IP details, issue is resolved. we need to generate truststore as well.

For someone who is looking for a solution, hope the below steps might help.

1. Generate server key and self signed server certificate keytool -genkey -alias serverkey -keyalg RSA -storetype PKCS12 -keystore serverkeystore.p12 -ext SAN=dns:abc.com,dns:localhost,ip:127.0.0.1

2. Generate client key and self signed client certificate keytool -genkey -alias clientkey -keyalg RSA -storetype PKCS12 -keystore clientkeystore.p12 -ext SAN=dns:def.com,dns:localhost,ip:127.0.0.1

3. Export the server certificate keytool -export -alias serverkey -file servercert.cer -keystore serverkeystore.p12

4. Export the client certificate keytool -export -alias clientkey -file clientcert.cer -keystore clientkeystore.p12

5. Import cert to $JAVA_HOME/jre/lib/security sudo keytool -import -trustcacerts -alias localhost -file localhost.crt -keystore $JAVA_HOME/jre/lib/security/cacerts

application.yml of gateway:

spring:
  application:
    name: gateway
server:
  port: 8443
  ssl:
    enabled: true
    key-store: classpath:serverkeystore.p12
    key-store-password: server
    key-alias: serverkey
eureka:
  instance:
    securePort: ${server.port}
    nonSecurePortEnabled: false
    securePortEnabled: true
    leaseRenewalIntervalInSeconds: 7
    leaseExpirationDurationInSeconds: 9
  client:
    serviceUrl:
      defaultZone: ${EUREKA_URI:http://localhost.com:8761/eureka/}
    registry-fetch-interval-seconds: 5
    register-with-eureka: true
    fetch-registry: true
    heartbeat-executor-thread-pool-size: 5
    eureka-service-url-poll-interval-seconds: 10
zuul:
  prefix: /service
  routes:
    producer:
      path: /employee/**
      strip-prefix: false
      serviceId: producer
ribbon:
  IsSecure: true
logging:
 file: logs/gateway.log
 level.root: INFO
 level.com.fujitsu.fnc.sdnfw.msvc: DEBUG