web-dev-qa-db-ja.com

独自の証明書を使用するJavaクライアントサーバーアプリ)のnginxを使用してトラフィックを適切にリダイレクトする

サーバーとクライアントアプリがあり、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
Alexios

一時的な回避策を見つけました。まだより良い解決策を探しています。

コマンドの下 に従うことで、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ファイルの元のパスワードが必要であり、証明書の秘密鍵がサーバー上で暗号化されないままになることです。

0
Alexios