У меня есть сервер и клиентское приложение, которые взаимодействуют друг с другом, используя соединение 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;
}
Выше представлена конфигурация для веб-сайта / сервиса, который я использую.
Веб-сайт работает правильно, и я могу получить к нему доступ через поддомен. 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.xx: 25566 /
, он подключается успешно .
В Postman, если я отправлю запрос на https: //1xx.2xx.xx: 25005 /
, он также не получит ответ.
Если я отправлю запрос на https: //1xx.2xx.xx: 25566 /
или http: //1xx.2xx.xx: 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 смогло успешно подключиться по URL-адресу https: //1xx.2xx.xx: 443 /
.
Единственным недостатком этого подхода является то, что вам нужен исходный пароль для файла JKS, а закрытый ключ сертификата остается незашифрованным на сервере.