使用 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 但不添加其他證書?
我確實找到了一個臨時的解決方法;仍在尋找更好的解決方案。
可以按照以下命令將 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 文件的原始密碼,並且證書的私鑰在伺服器上保持未加密狀態。