SSL конфигурация сервера Tomcat

Вопросам настройки SSL конфигурации сервера Tomcat и созданию безопасного SSL соединения с браузером посвящено немало статей в Интернете. Однако зачастую собственные попытки повторить достижения авторов статей заканчиваются неудачно : иногда Tomcat не хочет устанавливать SSL-соединение, но чаще браузер не распознает цифровой сертификат, открывает страницу с соответствующим предупреждением и отображает в адресной строке иконку небезопасного соединения.

Попробуем вместе на локальном компьютере настроить SSL конфигурацию сервера Tomcat и запустить простейшее WEB-приложение в безопасном SSL-соединении. Мы должны увидеть, что браузер Chrome отобразит нам в адресной строке, начинающейся с https (HyperText Transfer Protocol Secure — расширение протокола HTTP для поддержки шифрования), закрытый зеленый замок с надписью «Защищено». Поскольку само WEB-приложение не является предметом данной статьи, то возьмем готовый JSP пример hello-jsp, в котором я поменял только наименование проекта (это не принципиально).

Таким, образом, в этой статье будут рассмотрены следующие вопросы :

  • создание самоподписанного сертификата для локального WEB-приложения;
  • настройка SSL конфигурации сервера Tomcat;

Создание самоподписанного сертификата сервера

Что такое цифровой сертификат и как создать самоподписанный SSL сертификат подробно описано здесь. Поэтому здесь повторяться не будем, а остановимся только на том, как заставить этот сертификат работать на локальном компьютере.

Чтобы наш самоподписанный сертификат заработал на локальном компьютере (localhost) необходимо в обязательном порядке внести в него альтернативные имена SubjectAlternativeName (SAN). А вот в качестве одного из альтернативных имён указать localhost. То есть, URL нашего приложения hello-jsp на локальном компьютере будет иметь следующий адрес :

// незащищенное соединение
http://localhost:8080/hello-jsp/

// защищенное соединение
https://localhost:8443/hello-jsp/

С портом 8080 мы стартовали приложение при незащищенном соединении. Если все получится (а как иначе, статьи бы не было), то Tomcat откроет страницу приложения в защищенном соединении (по порту 8443), даже если мы будет пытаться открыть сайт на порту 8080.

При работе приложения под управлением WEB-сервера, например Apache, адрес приложения выглядел бы как http://hello-jsp. Доменное имя hello-jsp включают в атрибут CN (common name) опции описания владельца DN (Distinquished Name) цифрового сертификата. У нас же в адресной строке присутствует localhost, который мы должны включить в SAN.

Для создания сертификата используем утилиту keytool с командой -genkey. Символы переноса '\' использованы только для наглядности представления команды; в реальности они должны быть убраны и команда должна быть представлена одной строкой. Подробно о создании самоподписанного сертификата описано здесь.


C:\Program Files\Java\jdk1.8.0_161\bin\keytool \
  -v -genkey -dname "CN=hello-jsp, OU=Developers, \
   O=IT Systems Inc., L=Moscow, C=RF" \
  -ext SAN=dns:localhost,dns:www.hello-jsp.com \
  -alias tomcat -storetype jks -keystore keystore.jks \
  -validity 365 -keyalg RSA -keysize 2048 \
  -storepass mystorepass -keypass mystorepass
 

Необходимо обратить внимание на опцию -ext (4-ая строка), которая позволяет включить в сертификат альтернативные имена SAN, используя в качестве разделителя символ запятой. Помните, что наименования альтернативных имен должны начинаться с символов, т.е. если вместо localhost использовать значение 127.0.0.1 утилита keytool выбросит исключение :


java.lang.RuntimeException: java.io.IOException: DNSName components must begin with a letter.
 

Сертификат и закрытый ключ будут созданы в хранилище keystore.jks.

Настройка SSL конфигурации сервера Tomcat

Для тестирования работы Tomcat'a в защищенном SSL соединении были использованы две версии : Tomcat 7.0.55 и Tomcat 8.5.4. Нижеописанная конфигурация действительна для обоих версий сервера Tomcat.

Tomcat может использовать две различные SSL реализации :

  • JSSE (Java Secure Socket Extension) реализацию как часть Java runtime, начиная с версии 1.4;
  • APR (Apache Portable Runtime) реализацию, использующую по умолчанию OpenSSL engine.

Выбираем первый вариант и настраиваем Tomcat на использование библиотеки Java для безопасных сетевых соединений JSSE, в котором реализованы протоколы SSL и TLS. В первую очередь переносим в директорию {TOMCAT}/conf созданное на предыдущем шаге хранилище сертификата keystore.jks.

Файл конфигурации server.xml

Находим в директории инсталляции Tomcat'a {TOMCAT}/conf/ файл конфигурации server.xml и вносим следующий код, в котором указывается порт 8443, схема https, протокол TLS, тип хранилища JKS и его месторасположение "conf/keystore.jks". В обязательном порядке следует указать пароль доступа к хранилищу и алиас ключа/сертификата.

<!-- 
    Define a SSL/TLS HTTP/1.1 Connector on port 8443
    This connector uses the NIO implementation with the JSSE engine.
    When using the JSSE engine, the JSSE configuration attributes 
    must be used. -->
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
    port="8443" maxThreads="150" SSLEnabled="true" scheme="https"
    secure="true" clientAuth="false" sslProtocol="TLS"
    keystoreType="JKS" keystoreFile="conf/keystore.jks" 
    keystorePass="mystorepass" keyAlias="tomcat" />

Поскольку APR реализацию не используем, то комментируем строку определения слушателя AprLifecycleListener.

<!--APR library loader. Documentation at /docs/apr.html -->
<!--
  <Listener className="org.apache.catalina.core.AprLifecycleListener"
            SSLEngine="on" />
-->

Дексриптор приложения web.xml

Чтобы перевести WEB-приложение в режим защищенного соединения необходимо настроить дескриптор приложения web.xml. Поскольку, как правило, все WEB-приложения контейнера сервлетов работают либо в незащищенном режиме, либо в защищенном, то я не стал пробовать настраивать отдельный дескриптор приложения, а сразу же приступил к настройке дескриптора сервера Tomcat conf/web.xml.

Необходимо добавить следующий код в дескриптор {TOMCAT}/conf/web.xml в конец файла :

<security-constraint>
    <web-resource-collection>
        <web-resource-name>securedapp</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

Шаблон <url-pattern> говорит о том, что любую страницу/ресурс приложения ('/*') необходимо показывать в защищенном режиме, т.е. доступ должен быть через https. Значение CONFIDENTIAL тега <transport-guarantee> гарантирует работу приложения в SSL соединении.

Чтобы отключить защищенное SSL соединение необходимо только изменить CONFIDENTIAL на NONE. Это может быть использовано, если по каким либо причинам не продлили серверный SSL сертификат и браузер стал открывать предупреждающую об опасности страницу.

На этом, можно сказать, настройка конфигурации сервера Tomcat заканчивается. Полная англоязычная документация настройки SSL соединения Tomcat для версии 8.5 представлена здесь.

Если бы мы не включили в сертификат параметр SAN, то Tomcat перешел бы в защищенный режим всё равно, но Google Chrome открыл бы сначала страницу с предупреждением, а после нашего согласия на открытие страницы показал бы нам в строке URL изображение небезопасного соединения, как это представлено на следующем скриншоте. Полагаю, что подобный исход не многим бы понравился, тем более, что затрачены определенные усилия на установление нормального SSL соединения.

Но поскольку мы включили в цифровой сертификат параметр SAN, то строка URL при открытии в защищенном режиме страницы Tomcat'a (версия 7.0.55) приобретает другой вид :

Сертификат можно посмотреть (даже, если браузер не признает его). Для этого необходимо нажать мышкой на изображение замка в строке URL и в открывшемся контекстном окне нажать на ссылку «Valid» (в русскоязычной версии «Действительный»).

Теперь можно открыть страницу с примером hello-jsp. Все работает должным образом, а ведь с приложением ничего не делали.

Скриншоты сняты со страниц двух компьютеров с разными версиями Windows и Tomcat.

Размещение SSL сертификата в браузере Chrome

Браузер Chrome отобразил нам безопасное SSL соединение. На этом можно было бы и закончить повествование, но для полноты рассмотрим, как и где можно размещать цифровые сертификаты в Chrome.

Для размещения SSL сертификата в Google Chrome необходимо открыть страницу настроек (chrome://settings), раскрыть дополнительные настройки, найти ссылку «Настроить сертификаты» (Управление настройками и сертификатами HTTPS/SSL) и по ссылке открыть окно с сертификатами, скриншот которого представлен ниже. Импорт цифровых сертификатов необходимо выполнять на вкладке «Доверенные корневые центры сертификации».

Двусторонняя SSL аутентификация

При двухсторонней SSL аутентификации обе стороны (и сервер, и клиент) предоставляют сертификаты для проверки подлинности друг друга при установке шифрованного соединения. Механизм проверки в этом случае не представляет особой сложности : необходимо, чтобы сервер нашел ключ, у которого «subject distinguished name» совпадает с «issuer distinguished name» проверяемого ключа. Когда используются выданные центром сертификации ключи, то у сервера есть уже публичный ключ центра и свой ключ, подписанный этим центром. Но в случае с самоподписанным ключом необходимо публичный ключ, используемый клиентом, поместить в truststore сервера.

Выше было настроена конфигурация сервера Tomcat без учета доверенного хранилища. Сейчас дополним настройки параметрами доверенного хранилища; последние две строчки указывают на тип хранилища, его месторасположение и пароль (clientpass) :

<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
    port="8443" maxThreads="150" SSLEnabled="true" scheme="https"
    secure="true" clientAuth="false" sslProtocol="TLS"
    keystoreType="JKS" keystoreFile="conf/keystore.jks" 
    keystorePass="mystorepass" keyAlias="tomcat"
    truststoreType="JKS" truststoreFile="conf/truststore.jks" 
    truststorePass="clientpass" />

Как создавать хранилище и помещать (импортировать) в него сертификат подробно рассказано здесь.

  Рейтинг@Mail.ru