当Rserve启用TLS时Java Rconnection挂起

时间:2019-03-25 19:54:29

标签: java tls1.2 rserve jri

我有一个装有R和Rserve的Ubuntu VM,可以进行远程调用。我从终端通过调试模式启动Rserve:

R CMD Rserve.dbg

这是输出:

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.

我使用OPENSSL生成了密钥和自签名证书。

现在在客户端,我有一个Java应用程序只是请求Rserve放在其上的R版本作为功能测试:

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();
    }
}

问题是客户端代码挂在对RConnection构造函数的调用上。我已经放了十分钟了,直到我杀死服务器,一切都没有改变。在服务器端,我只看到:

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

目前我找不到任何可提供帮助的文档。这可能是客户端配置问题吗?

此外,如果我从Rserv.conf中删除了所有TLS配置项,则Rserve可以正常工作,并且此客户端代码没有问题,因此我知道它已正确设置。

1 个答案:

答案 0 :(得分:0)

我自己弄清楚了。实际上,这是一个客户端配置问题。我需要使用SSLSocket创建RConnection,还将服务器证书导入到Java信任库中。

相关的客户端代码更改为此:

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

构造函数RConnection(Socket s)显然不在REngine jar中,所以我抓住了the source itself并将其放在我的项目中,因为它包含在其中。

由于证书不在信任库中,因此此时运行javax.net.ssl.SSLHandshakeException。所以我像这样使用OPENSSL从服务器撤回了证书:

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

然后我将该证书文件移至%JAVA_HOME%\jre\lib\security并运行它以导入证书:

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

它有效! Wireshark确认所有数据包现在都已加密。

资源:

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

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

Digital Certificate: How to import .cer file in to .truststore file using?