title: Okhttp 3 (android) : connecting to ip address with self signed ssl
body: <p>I am currently attempting to connect to a server which has no domain name and is only reachable by its ip address. I previously attempted to do it by using the library volley, but after spending a day of research I couldn't figure out why the ssl handshake wouldn't work. after switching to Okhttp I got the warning:</p>
  
  <blockquote>
    <p>javax.net.ssl.SSLPeerUnverifiedException: Hostname 185.101.92.193 not verified:<br>
    certificate: sha256/QMgPlAslWrBi1dd/P17AKxJCniO2RfHQ5MufVO5Xji4=<br>
    DN:   1.2.840.113549.1.9.1=#1619626c61636b6a61636b34323636323440676d61696c2e636f6d,CN=185.101.92.193,O=Internet Widgits Pty Ltd,L=Berlin,ST=Berlin,C=DE<br>
    subjectAltNames: []</p>
  </blockquote>
  
  <p>Now this problem has already been addressed on github: <a href="https://github.com/square/okhttp/issues/1467" rel="nofollow noreferrer">https://github.com/square/okhttp/issues/1467</a></p>
  
  <p>I have "resolved" the problem with the following code (look at HostnameVerifier at the bottom): </p>
  
  <pre><code>// loading CAs from an InputStream
          try {
              CertificateFactory cf = CertificateFactory.getInstance("X.509");
              InputStream cert = context.getResources().openRawResource(R.raw.servercert);
              Certificate ca;
              try {
                  ca = cf.generateCertificate(cert);
              } finally {
                  cert.close();
              }
  
              // creating a KeyStore containing our trusted CAs
              String keyStoreType = KeyStore.getDefaultType();
              KeyStore keyStore = KeyStore.getInstance(keyStoreType);
              keyStore.load(null, null);
              keyStore.setCertificateEntry("ca", ca);
  
              // creating a TrustManager that trusts the CAs in our KeyStore
              String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
              TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
              tmf.init(keyStore);
  
              // creating an SSLSocketFactory that uses our TrustManager
              SSLContext sslContext = SSLContext.getInstance("TLS");
              sslContext.init(null, tmf.getTrustManagers(), null);
              client = new OkHttpClient.Builder().sslSocketFactory(sslContext.getSocketFactory())
                      .hostnameVerifier(new HostnameVerifier() {
                          @Override
                          public boolean verify(String s, SSLSession sslSession) {
                              if(s.equals(myIPAddress)){
                                  return true;
                              }else{
                                  return false;
                              }
                          }
                      })
                      .build();
          }catch (Exception e){
              e.printStackTrace();
          }
  </code></pre>
  
  <p>Now this kinda looks like bad practice to me and my actual question is: what problems could arise from implementing the HostnameVerifier like this (security-wise) and how could I solve this matter in a more sophisticated way?</p>