Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support custom SNI for SSL connection #1503

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ public static Map<ClickHouseOption, Serializable> toClientOptions(Map<?, ?> prop
private final String sslRootCert;
private final String sslCert;
private final String sslKey;
private final String serverHostName;
private final String keyStoreType;
private final String trustStore;
private final String trustStorePassword;
Expand Down Expand Up @@ -349,6 +350,7 @@ public ClickHouseConfig(Map<ClickHouseOption, Serializable> options, ClickHouseC
this.sslRootCert = getStrOption(ClickHouseClientOption.SSL_ROOT_CERTIFICATE);
this.sslCert = getStrOption(ClickHouseClientOption.SSL_CERTIFICATE);
this.sslKey = getStrOption(ClickHouseClientOption.SSL_KEY);
this.serverHostName = getStrOption(ClickHouseClientOption.SERVER_HOST_NAME);
this.keyStoreType = getStrOption(ClickHouseClientOption.KEY_STORE_TYPE);
this.trustStore = getStrOption(ClickHouseClientOption.TRUST_STORE);
this.trustStorePassword = getStrOption(ClickHouseClientOption.KEY_STORE_PASSWORD);
Expand Down Expand Up @@ -630,6 +632,8 @@ public String getSslKey() {
return sslKey;
}

public String getServerHostName() { return serverHostName; }

public String getKeyStoreType() {
return keyStoreType;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.clickhouse.client.config.ClickHouseClientOption;
import com.clickhouse.client.config.ClickHouseDefaults;
import com.clickhouse.client.config.ClickHouseSslMode;
import com.clickhouse.client.config.ClickhouseSSLSocketFactory;
import com.clickhouse.config.ClickHouseOption;
import com.clickhouse.data.ClickHouseChecker;
import com.clickhouse.data.ClickHouseUtils;
Expand Down Expand Up @@ -620,7 +621,7 @@ static ClickHouseNode probe(String host, int port, ClickHouseSslMode mode, Strin
return probe(host, port, timeout);
}

SSLSocketFactory factory = sslContext.getSocketFactory();
SSLSocketFactory factory = new ClickhouseSSLSocketFactory(sslContext.getSocketFactory(), config);
ClickHouseDnsResolver resolver = ClickHouseDnsResolver.getInstance();
ClickHouseProtocol p = ClickHouseProtocol.HTTP;
InetSocketAddress address = resolver != null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,8 @@ public enum ClickHouseClientOption implements ClickHouseOption {
* SSL key.
*/
SSL_KEY("sslkey", "", "RSA key in PKCS#8 format.", true),

SERVER_HOST_NAME("server_host_name", "", "The ClickHouse server hostname as identified by the CN or SNI of its TLS certificate. Set this to avoid SSL errors when connecting through a proxy or tunnel with a different hostname"),
/**
* Key Store type.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.clickhouse.client.config;

import com.clickhouse.client.ClickHouseConfig;

import javax.net.ssl.*;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.List;

public class ClickhouseSSLSocketFactory extends SSLSocketFactory {
private SSLSocketFactory delegate;
private ClickHouseConfig config;

public ClickhouseSSLSocketFactory(SSLSocketFactory delegate, ClickHouseConfig config) {
this.delegate = delegate;
this.config = config;
}

@Override
public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
}

@Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}

private void setServerNameIndication(SSLSocket socket) {
String serverHostName = this.config.getServerHostName();
if(serverHostName != null && !serverHostName.isEmpty()) {
SSLParameters sslParams = socket.getSSLParameters();
sslParams.setServerNames(List.of(new SNIHostName(serverHostName)));
socket.setSSLParameters(sslParams);
}
}

private Socket setup(Socket socket) {
setServerNameIndication((SSLSocket) socket);
return socket;
}

@Override
public Socket createSocket(Socket socket, final String host, int port, boolean autoClose) throws IOException {
return setup(delegate.createSocket(socket, host, port, autoClose));
}

@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return setup(delegate.createSocket(host, port));
}

@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return setup(delegate.createSocket(host, port, localHost, localPort));
}

@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return setup(delegate.createSocket(host, port));
}

@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return setup(delegate.createSocket(address, port, localAddress, localPort));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;

import com.clickhouse.client.config.ClickhouseSSLSocketFactory;
import io.grpc.ManagedChannelBuilder;
import io.grpc.okhttp.OkHttpChannelBuilder;
import com.clickhouse.client.ClickHouseConfig;
Expand Down Expand Up @@ -47,7 +49,7 @@ protected void setupSsl() {
Optional<SSLContext> sslContext = ClickHouseSslContextProvider.getProvider()
.getSslContext(SSLContext.class, config);
if (sslContext.isPresent()) {
builder.useTransportSecurity().sslSocketFactory(sslContext.get().getSocketFactory());
builder.useTransportSecurity().sslSocketFactory(new ClickhouseSSLSocketFactory(sslContext.get().getSocketFactory(), config));
}
} catch (SSLException e) {
throw new IllegalStateException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.clickhouse.client.ClickHouseSslContextProvider;
import com.clickhouse.client.config.ClickHouseClientOption;
import com.clickhouse.client.config.ClickHouseSslMode;
import com.clickhouse.client.config.ClickhouseSSLSocketFactory;
import com.clickhouse.client.http.config.ClickHouseHttpOption;
import com.clickhouse.data.ClickHouseChecker;
import com.clickhouse.data.ClickHouseExternalTable;
Expand Down Expand Up @@ -122,7 +123,7 @@ private HttpURLConnection newConnection(String url, boolean post) throws IOExcep

secureConn.setHostnameVerifier(verifier);
if (sslContext != null) {
secureConn.setSSLSocketFactory(sslContext.getSocketFactory());
secureConn.setSSLSocketFactory(new ClickhouseSSLSocketFactory(sslContext.getSocketFactory(), c));
}
}

Expand Down