使用 nginx 为使用自有证书的 Java 客户端-服务器应用程序正确重定向流量

使用 nginx 为使用自有证书的 Java 客户端-服务器应用程序正确重定向流量

我有一个服务器和一个客户端应用程序,它们使用 Https 连接和自己的证书(.jks 文件)相互通信。服务器侦听端口 443,客户端使用专用 IP 和服务器端口连接到它。

最近,我想在同一台机器上添加一个网站/服务。我为该网站注册了一个新的子域名并为其获取了 SSL 证书。我正在尝试找到一种方法,让网站和 Java 应用程序都能获取发送到端口 443 上的服务器的请求。网站将获取与分配给它的子域名相关的请求,而 Java 应用程序将获取与子域名无关的请求,并且只拥有服务器的 IP。

为了测试目的,首先我尝试使用不同的端口来重定向与 Java 应用程序相关的流量。

 server {

  listen           127.0.0.1;
  listen           25005;
  server_name      1xx.2xx.x.x;
  root             /var/www/html;

  location / {
    proxy_pass https://127.0.0.1:25566;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }

}

以上是该重定向的配置。

server {
    listen 80;
    return 301 https://$host$request_uri;
}

include /etc/nginx/websiterelated-include/upstreams;

server {
    listen 443;
    server_name subdomain.domain.com;

    ssl on;
    ssl_certificate /etc/ssl/certs/websiterelated.combined-chain.crt;
    ssl_certificate_key /etc/ssl/private/websiterelated.key;

    location /user_avatars {
        add_header X-Content-Type-Options nosniff;
        add_header Content-Security-Policy "default-src 'none' img-src 'self'";
        include /etc/nginx/websiterelated-include/uploads.types;
        alias /home/websiterelated/uploads/avatars;
    }

    location /local-static {
        alias /home/websiterelated/local-static;
    }

    include /etc/nginx/websiterelated-include/certbot;
    include /etc/nginx/websiterelated-include/app;
    include /etc/nginx/websiterelated-include/uploads.route;
}

以上是我使用的网站/服务的配置。

网站运行正常,我可以通过 subdomain.domain.com 访问该网站。使用 Java 应用程序时,我遇到了一些问题:如果我尝试使用 Java 客户端连接到

https://1xx.2xx.x.x:25005/

它失败并给出此错误:

javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
    at sun.security.ssl.InputRecord.handleUnknownRecord(InputRecord.java:710)
    at sun.security.ssl.InputRecord.read(InputRecord.java:527)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
    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.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1283)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1258)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
    at com.plugnbyte.httpclient.core.HttpClient.sendRequestSynchronous(HttpClient.kt:105)
    at com.plugnbyte.httpclient.core.HttpClient$sendRequest$requestThread$1.run(HttpClient.kt:53)
    at java.lang.Thread.run(Thread.java:745)

如果我尝试连接,https://1xx.2xx.x.x:25566/则会连接成功。

使用 Postman,如果我向其发送请求,https://1xx.2xx.x.x:25005/也无法收到响应。如果我将请求发送到https://1xx.2xx.x.x:25566/或,http://1xx.2xx.x.x:25005/则会成功收到响应。

据我了解,重定向有效,但仅限于 http。是否可以将其更改为 https 但不添加其他证书?

答案1

我确实找到了一个临时的解决方法;仍在寻找更好的解决方案。

按照以下步骤将 JKS 文件转换为 nginx 所需的文件以下命令

keytool -importkeystore -srckeystore {keystore.jks} -destkeystore {pkcs12.p12} -deststoretype PKCS12

openssl pkcs12 -nokeys -in {pkcs12.p12} -out {certificate-chain.pem}

openssl pkcs12 -nocerts -nodes -in {pkcs12.p12} -out {unencrypted-key.key}

完成后,将 Java 应用程序的配置文件更改为以下内容:

 server {

    ssl on;
    ssl_certificate /root/certs/certificate-chain.pem;
    ssl_certificate_key /root/certs/unecrypted-key.key;

  listen           127.0.0.1;
  #listen           25005;
  listen           443;
  server_name      1xx.2xx.x.x;
  root             /var/www/html;

  location / {
    proxy_pass https://127.0.0.1:25566;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }

}

重新加载设置nginx -s reload,Java 应用程序就能使用https://1xx.2xx.x.x:443/URL 成功连接。

这种方法的唯一缺点是您需要 JKS 文件的原始密码,并且证书的私钥在服务器上保持未加密状态。

相关内容