Правильно перенаправляйте трафик с 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;
}

Выше представлена ​​конфигурация для веб-сайта / сервиса, который я использую.

Веб-сайт работает правильно, и я могу получить к нему доступ через поддомен. 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, но без добавления другого сертификата?

1
задан 4 January 2019 в 18:37
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 смогло успешно подключиться по URL-адресу https: //1xx.2xx.xx: 443 / .

Единственным недостатком этого подхода является то, что вам нужен исходный пароль для файла JKS, а закрытый ключ сертификата остается незашифрованным на сервере.

0
ответ дан 4 December 2019 в 03:21

Теги

Похожие вопросы