简体   繁体   English

当Rserve启用TLS时,Java Rconnection挂起

[英]Java Rconnection hangs when Rserve has TLS enabled

I have an Ubuntu VM with R and Rserve installed for remote calls. 我有一个安装了R和Rserve的Ubuntu VM用于远程调用。 I start Rserve in debug mode from the terminal with: 我从终端启动Rserve调试模式:

R CMD Rserve.dbg

And this is the output: 这是输出:

Rserve 1.8-6 () (C)Copyright 2002-2013 Simon Urbanek

Loading config file /etc/Rserv.conf
conf> command="remote", parameter="enable"
conf> command="plaintext", parameter="disable"
conf> command="encoding", parameter="utf8"
conf> command="pwdfile", parameter="/etc/RserveAuth.txt"
conf> command="auth", parameter="required"
conf> command="qap", parameter="disable"
conf> command="qap.tls.port", parameter="6311"
conf> command="tls.key", parameter="server.key"
conf> command="tls.cert", parameter="server.crt"
conf> command="tls.ca", parameter="rootCA.crt"
Loaded config file /etc/Rserv.conf

R version 3.5.3 (2019-03-11) -- "Great Truth"
Copyright (C) 2019 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

 - create_server(port = 6311, socket = <NULL>, mode = 0, flags = 0x800)
INFO: adding server 0x5618de18b9d0 (total 1 servers)
Rserve: Ok, ready to answer queries.

I generated the key and self-signed certificates with OPENSSL. 我用OPENSSL生成了密钥和自签名证书。

Now on the client side, I have a Java application just requesting the version of R that Rserve is sitting on top of as a test of functionality: 现在在客户端,我有一个Java应用程序只是请求Rserve的版本作为功能测试的顶部:

import org.rosuda.REngine.REXP;
import org.rosuda.REngine.Rserve.RConnection;

public class RJava {
    public static void main(String[] args) throws Exception{
        //Run R code on remote R installation via Rserve.
        String remoteIP="10.16.24.63"; //Ubuntu VM Box
        int port=6311;
        String user="TEST";
        String pass="12345";

        //Connect to the remote server.
        RConnection connection = new RConnection(remoteIP,port);//Remote server
        connection.login(user, pass);

        //Run a command.
        REXP x = connection.eval("R.version.string");
        System.out.println(x.asString());

        //Disconnect.
        connection.close();
    }
}

The problem is the client code hangs on the call to the RConnection constructor. 问题是客户端代码挂起对RConnection构造函数的调用。 I've let it go for ten minutes and nothing changes until I kill the server. 在我杀死服务器之前,我已经放了十分钟而且没有任何变化。 On the server side I just see: 在服务器端,我只看到:

INFO: accepted connection for server 0x5618de18b9d0, calling connected
connection accepted.

I can't find any documentation to help at this point. 我现在找不到任何文档可以提供帮助。 Is this possibly a client configuration problem? 这可能是客户端配置问题吗?

Also, if I remove all the TLS configuration items from Rserv.conf , Rserve will work as expected no problem with this client code, so I know it is set up correctly. 此外,如果我从Rserv.conf删除所有TLS配置项,Rserve将按预期工作,此客户端代码没有问题,所以我知道它已正确设置。

I figured this out on my own. 我自己想出来了。 It was in fact a client configuration problem. 这实际上是一个客户端配置问题。 I needed to create the RConnection with an SSLSocket and also import the server certificate to the java truststore. 我需要使用SSLSocket创建RConnection,并将服务器证书导入java信任库。

Relevant client code changed to this: 相关客户端代码更改为:

SSLSocketFactory sslsocketfactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(remoteIP, port);
//Connect to the remote server.
RConnection connection = new RConnection(sslsocket);

NB the constructor RConnection(Socket s) is apparently not in the REngine jar, so I grabbed the source itself and put that in my project because it is included there. NB构造函数RConnection(Socket s)显然不在REngine jar中,因此我抓住了源本身并将其放入我的项目中,因为它包含在那里。

Running at this point threw a javax.net.ssl.SSLHandshakeException because the cert wasn't in the truststore. 此时运行会抛出javax.net.ssl.SSLHandshakeException因为证书不在信任库中。 So I withdrew the cert from the server using OPENSSL like this: 所以我使用OPENSSL从服务器撤回了证书,如下所示:

echo "" | openssl s_client -connect 10.16.24.63:6311 | openssl x509 -out server.crt

Then I moved that cert file to %JAVA_HOME%\\jre\\lib\\security and ran this to import the certificate: 然后我将该cert文件移动到%JAVA_HOME%\\jre\\lib\\security并运行它以导入证书:

keytool -import -alias myAlias -file server.crt -keystore cacerts -storepass changeit

And it works! 它的工作原理! Wireshark confirms all the packets are now encrypted. Wireshark确认所有数据包现在都已加密。

Resources: 资源:

https://stats-rosuda-devel.listserv.uni-augsburg.narkive.com/g5VM1afB/encryption-with-rserve-1-8-1 https://stats-rosuda-devel.listserv.uni-augsburg.narkive.com/g5VM1afB/encryption-with-rserve-1-8-1

https://www.baeldung.com/java-ssl https://www.baeldung.com/java-ssl

Digital Certificate: How to import .cer file in to .truststore file using? 数字证书:如何将.cer文件导入到.truststore文件中?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM