在反向代理后面访问 elastiC

Acessing elasctiDB behind reverse proxy

我有一个 RestHighLevelClient 连接到一个反向代理后面的远程 elasticDB,它剥离了 ssl。

        val restClientBuilder: RestClientBuilder = RestClient
                .builder(HttpHost(hostname, port, scheme))

        if(username.isNotEmpty()){
            val credentialsProvider: CredentialsProvider = BasicCredentialsProvider()
            credentialsProvider.setCredentials(AuthScope.ANY, UsernamePasswordCredentials(username, password))
            restClientBuilder.setHttpClientConfigCallback { h: HttpAsyncClientBuilder -> h.setDefaultCredentialsProvider(credentialsProvider).setSSLHostnameVerifier { _, _ -> true }.setSSLContext(SSLContext.getDefault()) }
        }

client = RestHighLevelClient(restClientBuilder)

当我打电话时

client.index(indexRequest, RequestOptions.DEFAULT)

我得到一个handshake_failure异常

javax.net.ssl.SSLException: Received fatal alert: handshake_failure

如所述here and here 我检查了日志并找到了 ClientHello

*** ClientHello, TLSv1.2
RandomCookie:  GMT: 1307888763 bytes = { 137, 187, 7, 199, 3, 82, 79, 49, 175, 115, 114, 160, 22, 241, 240, 60, 237, 136, 239, 232, 108, 236, 249, 79, 139, 90, 119, 136 }
Session ID:  {95, 24, 10, 176, 230, 223, 52, 137, 2, 146, 170, 240, 61, 10, 177, 36, 223, 167, 33, 19, 225, 19, 213, 54, 22, 220, 239, 77, 199, 139, 52, 23}
Cipher Suites: [Unknown 0x13:0x1, Unknown 0x13:0x2, Unknown 0x13:0x3, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, Unknown 0xcc:0xa9, Unknown 0xcc:0xa8, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA]
Compression Methods:  { 0 }
Extension server_name, server_name: [type=host_name (0), value=localhost]
Unsupported extension type_23, data: 
Extension renegotiation_info, renegotiated_connection: <empty>
Extension elliptic_curves, curve names: {unknown curve 29, secp256r1, secp384r1}
Extension ec_point_formats, formats: [uncompressed]
Unsupported extension type_35, data: 
Extension signature_algorithms, signature_algorithms: SHA256withECDSA, Unknown (hash:0x8, signature:0x4), SHA256withRSA, SHA384withECDSA, Unknown (hash:0x8, signature:0x5), SHA384withRSA, Unknown (hash:0x8, signature:0x6), SHA512withRSA, SHA1withRSA
Unsupported extension type_51, data: 00:24:00:1d:00:20:6a:06:37:c2:47:97:e9:87:59:c6:0e:8f:9a:7f:12:81:18:20:18:49:77:b3:d4:11:71:37:0e:13:3d:de:6f:10
Unsupported extension type_45, data: 01:01
Unsupported extension type_43, data: 08:03:04:03:03:03:02:03:01
***

和ServerHello

*** ServerHello, TLSv1.2
RandomCookie:  GMT: 1595412045 bytes = { 85, 81, 154, 66, 129, 137, 233, 228, 170, 170, 0, 28, 94, 221, 152, 50, 25, 2, 31, 115, 127, 103, 180, 78, 173, 152, 8, 173 }
Session ID:  {95, 24, 10, 176, 230, 223, 52, 137, 2, 146, 170, 240, 61, 10, 177, 36, 223, 167, 33, 19, 225, 19, 213, 54, 22, 220, 239, 77, 199, 139, 52, 23}
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
Cipher suite:  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

客户端和服务器都同意密码套件 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

然后是加密和明文形式的请求。之后是另一个以

结尾的 ClientHello
[Raw read]: length = 5
0000: 15 03 03 00 02                                     .....
[Raw read]: length = 2
0000: 02 28                                              .(
I/O dispatcher 25, READ: TLSv1.2 Alert, length = 2
I/O dispatcher 25, RECV TLSv1.2 ALERT:  fatal, handshake_failure
I/O dispatcher 25, fatal: engine already closed.  Rethrowing javax.net.ssl.SSLException: Received fatal alert: handshake_failure
I/O dispatcher 25, fatal: engine already closed.  Rethrowing javax.net.ssl.SSLException: Received fatal alert: handshake_failure
2020-07-22 12:00:45.360 ERROR 78321 --- [io-8081-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception

java.io.IOException: Received fatal alert: handshake_failure

I/O dispatcher 25, READ: TLSv1.2 Alert, length = 2

给出 hint 密码套件的非协议 - 但在上面的行中双方都同意了一个套件。

有谁知道这里发生了什么以及如何解决异常?

仍然缺少合适的解决方案,但我找到了一个行之有效的解决方法。我正在使用 curl 将数据传输到 elastic-Instance

val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").create()
val fileContent = createTempFile(prefix = "data")
fileContent.writeText(gson.toJson(it))
val fileCommand = createTempFile()
val command = "curl --user $username:$password -PUT '$scheme://$hostname:$port/data/_doc' -H 'Content-Type: application/json' -d @${fileContent.absolutePath}"
fileCommand.writeText(command)

val result = "bash ${fileCommand.absolutePath}".runCommand(createTempDir())
logger.debug(result)
fileCommand.delete()
fileContent.delete()

runCommand 的动机是 this post。首先,我尝试只使用一个文件,但特殊字符的转义没有按预期工作。

使用此方法不会发生握手失败,这表明我之前的代码中存在错误。