Jenkins 在 nginx SSL 反向代理后面使用 JNLP

Jenkins 在 nginx SSL 反向代理后面使用 JNLP

我想使用 JNLP 将 jenkins 从服务器连接到 jenkins 主服务器。主服务器运行在 SSL nginx 代理后面根据官方文档设置. 除了本文档之外,我还遇到了与证书相关的问题。

目前,我只能使用不安全的 HTTP 连接来使 JNLP 无头从属设备与主设备连接工作,而不能使用 HTTPS(尽管我的 jenkins 仪表板通常可以工作)。我使用由我自己的自定义 CA 证书(基于 openssl 的 x509)签名的自签名证书。

那么我该如何告诉我的从属 Java 二进制文件信任我的 SSL CA 证书?我试过了。

# add CA certificate to key store
$ keytool -import -file /usr/local/share/ca-certificates/my_ca.crt -alias my_ca -storepass mypassword

# try to reference keystore to JNLP headless call
$ java -Djavax.net.ssl.keyStorePassword=mypassword -Djavax.net.ssl.keyStore=/home/myuser/.keystore -jar slave.jar -jnlpUrl https://proxied-jenkins.example.com/computer/testslave/slave-agent.jnlp

实际上,JAVA 似乎不会在提供的密钥库中查找证书。我这里犯了什么错误?

编辑

使用 jenkins cli 时也会出现类似/相同的问题。根据, 现在我认为这与我的证书的信任无关因为我看不到javax.net.ssl.SSLHandshakeException

我刚刚收到连接重置

Failing to obtain https://proxied-jenkins.example.com/computer/testslave/slave-agent.jnlp
java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:196)
    at java.net.SocketInputStream.read(SocketInputStream.java:122)
    at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
    at sun.security.ssl.InputRecord.read(InputRecord.java:480)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:934)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
    at hudson.remoting.Launcher.parseJnlpArguments(Launcher.java:269)
    at hudson.remoting.Launcher.run(Launcher.java:219)
    at hudson.remoting.Launcher.main(Launcher.java:192)

..所以我假设我的代理配置有问题。我从反向代理配置并添加以下配置以强制使用 SSL:

upstream jenkins-upstream {
  server unproxied-jenkins.example.com:8080 fail_timeout=0;
}

server {
  listen 80;
  server_name proxied-jenkins.example.com;
  return 301 https://$host$request_uri;
}
server {
  listen 443;
  server_name proxied-jenkins.example.com;

  #this is the jenkins web root directory (mentioned in the /etc/default/jenkins file)
  root            /var/run/jenkins/war/;

  ssl on;
  ssl_certificate /etc/nginx/conf.d/proxied-jenkins.example.com.crt;
  ssl_certificate_key /etc/nginx/conf.d/proxied-jenkins.example.com.key;
  ssl_protocols TLSv1.2;
  ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;

  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:10m;

  [...] # continuing according to jenkins documentation
  location @jenkins {
      proxy_pass                  http://jenkins-upstream
      [....]
  }
  [....]
}

再次,当更改为不安全的 HTTP 时,JNLP 和 jenkins-cli 会按预期工作。那么错误是什么?
也许我需要传递额外的标头信息?也许我需要在代理设置中进行额外的 SSL 配置?

答案1

(根据评论反馈进行扩展)

该服务器配置为需要协议版本 TLSv1.2(仅),以及使用至少 AES-GCM 或 256 位 AES 之一的密码套件,以及 DHE 或 ECDHE 密钥交换(OpenSSL 和 nginx 在某些情况下使用变体拼写 EDH 和 EECDH,包括这种情况)。

Oracle 或 OpenJDK 中的 JSSE 客户端JDK7 默认不提供 TLSv1.2 或 1.1(不知道 IBM 是否拥有自己的加密提供商)但它们已经实现并且可以启用;因为(Https)URLConnection可以使用系统属性来完成此操作https.protocols。(或者通过覆盖其套接字工厂,但系统属性通常更容易。)但 JDK7没有实现 GCM,而 Oracle版本(但不是 OpenJDK 版本)禁止 256 位对称加密,除非你安装“JCE无限力量来自 Oracle 网站的“管辖权政策文件”;参见https://stackoverflow.com/a/33712287/2868801并且可能https://stackoverflow.com/questions/30350120/sslhandshakeexception-while-connecting-to-a-https-site

相比之下,JDK8(Oracle 和 OpenJDK)默认提供 TLSv1.2 和 1.1,并实现 GCM,因此它可以在没有无限强度策略的情况下进行连接。

7 和 8 都支持 DHE 和 ECDHE 密钥交换。但对于其他处于类似情况的人来说JDK6:除非 ECDHE 有效,否则你可以添加第三方 ECC 原语提供程序,bcprov例如http://www.BouncyCastle.org

答案2

对于那些根据标题而不是问题内容到达此页面的谷歌用户,并且希望 JNLP 从属服务器连接到在单独的服务器而不是反向代理服务器上运行的反向代理 Jenkins,请参阅我的回答Jenkins:如何在 Nginx 反向代理后面配置 Jenkins,以便 JNLP 从属设备进行连接

相关内容