February 18, 2019

server_name 修改(基于 OkHttp3)

OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(new SSLSocketFactory() {
   ...
   ...
   @Override
   public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
       //此方法为真正创建SSL Socket的地方
       SSLCertificateSocketFactory sslSocketFactory = 
           (SSLCertificateSocketFactory) SSLCertificateSocketFactory
                                                   .getInsecure(0,null);
       SSLSocket sslSocket = (SSLSocket) sslSocketFactory
                                       .createSocket(s, host, port, autoClose);
       sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols());
       
       //method 1, 直接设置SNIHostName, API 24及以上支持
       SSLParameters parameters = new SSLParameters();
       SNIHostName sniHostName = new  SNIHostName("sni.cashzhang.com");
       List list = new ArrayList<SNIHostName>();
       list.add(sniHostName);
       parameters.setSer0verNames(list);
       sslSocket.setSSLParameters(parameters);
       
       //method 2, Hook SSLSocket.setHostname(p1)方法
       try {
           Method method = sslSocket.getClass().getMethod("setHostname", String.class);
           method.invoke(sslSocket, "sni.cashzhang.com");
       } catch (Exception ex) {
       }
       
       //method 3, 通过SSLCertificateSocketFactory::setHostname(p1, p2),API 17及以上支持
       sslSocketFactory.setHostname(sslSocket, "sni.cashzhang.com");
       
       return sslSocket;
   }
   ...
   ...
})

改写OkHttp3源码,手动重新编译提取Jar

okhttp/okhttp/src/main/java/okhttp3/internal/connection/RealConnection.java
private void connectTls(ConnectionSpecSelector connectionSpecSelector) throws IOException{
...
...
   if (connectionSpec.supportsTlsExtensions()) {
       platform.get().configureTlsExtensions(
       sslSocket, /*address.url().host()*/ null, address.protocols());
       //AndroidPlatform::configureTlsExtensions(p1, p2, p3)中,若p2(address.url().host())不为空
       //即支持TLS拓展,请求目标host非IP地址形式,会为此socket设置server_name
       //为实现手动指定server_name,修改此处
   }
...
...
}