Взаимная аутентификация с Tomcat 7

Я пытаюсь настроить веб-службу Java, работающую в Tomcat 7, чтобы использовать взаимную (двухстороннюю) аутентификацию. Похоже, что независимо от того, что я делаю, подключение к службе на защищенном порту не работает.

вот что я сделал, чтобы создать сертификаты и хранилища ключей и такие:

//create the key and certificate for the tomcat server.
keytool -genkey -v -alias tomcat -keyalg RSA -validity 3650 -keystore tomcat.keystore

//create the key and certificate for the client machine.
keytool -genkey -v -alias clientkey -keyalg RSA -storetype PKCS12 -keystore client.p12

//export the client key
keytool -export -alias clientkey -keystore client.p12 -storetype PKCS12 -rfc -file client.cer

//import the client key into the server keystore
keytool -import -v -file client.cer -keystore tomcat.keystore

вот соединитель на сервере.xml-файл:

<Connector port="8443"
    maxThreads="150"
    scheme="https"
    secure="true"
    sslProtocol="TLS"
    clientAuth="true"
    keystoreFile="tomcat.keystore"
    keystorePass="tomcat"
    truststoreFile="tomcat.keystore"
    truststorePass="tomcat"/>

пользователи tomcat.xml-файл выглядит следующим образом:

<tomcat-users>
    <role rolename="tomcat"/>
    <role rolename="admin"/>
    <!-- note that the actual values for CN, OU, O, L, ST are different, but they match the values created in the client certificate -->
    <user username="CN=name, OU=unit, O=org, L=locality, ST=state, C=US" password="null" roles="admin" />
</tomcat-users>

установлены следующие значения запуск:

-Djavax.net.ssl.keyStoreType=jks
-Djavax.net.ssl.keyStore=tomcat.keystore
-Djavax.net.ssl.keyStorePassword=tomcat
-Djavax.net.ssl.trustStore=tomcat.keystore
-Djavax.net.ssl.trustStorePassword=tomcat
-Djavax.net.debug=SSL

наконец, я скопировал клиент.файл p12 на мою клиентскую машину и импортировал его в клиентские сертификаты Firefox.

первая проблема: Когда я нажимаю конечную точку на своей службе (пример -https://my.server.com:8443/test) из Firefox я получаю ответ "безопасное соединение не удалось". SSL получил запись, превышающую максимально допустимую длину. (Код ошибки: ssl_error_rx_record_too_long)

вторая проблема: Я не очень хочу запустить этот разъем на порт 8443. Я хочу запустить его на порту 7800 (который является стандартом нашей компании для HTTPS). Когда я меняю порт на соединителе на 7800 и пытаюсь попасть в конечную точку (пример -https://my.server.com:7800/test) тогда он никогда не разрешает страницу.

Итак, где-то я, очевидно, пропустил важную часть. Кто-нибудь видит мою ошибку?

обновление: после обратной связи от @Dave G

запуск команда:

openssl s_client -connect localhost:8443 -showcerts

производит следующий вывод:

CONNECTED(00000003)
140642290976584:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:766:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 263 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---

Я также добавил-Djavax.сеть.debug=SSL для запуска. Это порождает следующее В начале catalina.файл:

trustStore is: tomcat.keystore
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert:
  Subject: CN=localhost, OU=unit, O=org, L=Springfield, ST=MO, C=US
  Issuer:  CN=localhost, OU=unit, O=org, L=Springfield, ST=MO, C=US
  Algorithm: RSA; Serial number: 0x5485b5a5
  Valid from Mon Dec 08 14:28:53 UTC 2014 until Thu Dec 05 14:28:53 UTC 2024

adding as trusted cert:
  Subject: CN=William Jackson, OU=unit, O=org, L=Springfield, ST=MO, C=US
  Issuer:  CN=William Jackson, OU=unit, O=org, L=Springfield, ST=MO, C=US
  Algorithm: RSA; Serial number: 0x5485b6af
  Valid from Mon Dec 08 14:33:19 UTC 2014 until Sun Mar 08 14:33:19 UTC 2015

trigger seeding of SecureRandom
done seeding SecureRandom

а потом много:

Ignoring unavailable cipher suite: <suite name>
Ignoring unsupported cipher suite: <suite name>

4 ответов


Ok-после копания намного больше, я, наконец, получил эту работу. Большое спасибо @Dave G и этот учебник:http://java-notes.com/index.php/two-way-ssl-on-tomcat из которого большинство этих инструкций перефразированы.

как правило, шаги для получения функции взаимной аутентификации следующие:

  1. создайте сертификат для сервера tomcat. Клиент должен доверять этому сертификату.
  2. создать хранилище ключей для tomcat сервер и импортируйте в него сертификат сервера.
  3. создать сертификат для клиента. Сервер должен доверять этому сертификату.
  4. импорт клиент сертификат сервер хранилище
  5. обновите сервер tomcat.xml-файл с правильным соединителем XML.

вышеуказанные шаги необходимы на сервере. После завершения настройки клиента выполните следующий:

  1. скопируйте сертификат клиента с сервера на клиент.
  2. используйте сертификат клиента при общении с сервером (этот процесс зависит от характера клиентского приложения).

для конфигурации сертификата я выполнил следующее на машине сервера:

# For the following commands, set the values in parenthesis to be whatever makes sense for your environment.  The parenthesis are not necessary for the command.

# This is an all-in-one command that generates a certificate for the server and places it in a keystore file, while setting both the certifcate password and the keystore password.
# The net result is a file called "tomcat.keystore". 

keytool -genkeypair -alias (serveralias) -keyalg RSA -dname "CN=(server-fqdn),OU=(organizationalunit),O=(organization),L=(locality),ST=(state),C=(country)" -keystore tomcat.keystore -keypass (password) -storepass (password)

# This is the all-in-one command that generates the certificate for the client and places it in a keystore file, while setting both the certificate password and the keystore password.
# The net result is a file called "client.keystore"

keytool -genkeypair -alias (clientalias) -keyalg RSA -dname "CN=(client),OU=(organizationalunit),O=(organization),L=(locality),ST=(state),C=(country)" -keypass (password) -keystore client.keystore -storepass (password) 

# This command exports the client certificate.  
# The net result is a file called "client.cer" in your home directory.

keytool -exportcert -rfc -alias (clientalias) -file client.cer -keypass (password) -keystore client.keystore -storepass (password)

# This command imports the client certificate into the "tomcat.keystore" file.

keytool -importcert -alias (clientalias) -file client.cer -keystore tomcat.keystore -storepass (password) -noprompt

сертификаты сейчас должны быть настроены соответствующим образом. Следующим шагом является настройка соединителя в tomcat сервер.XML. Добавьте элемент соединителя, который выглядит следующим образом:

<Connector port="8443"
    maxThreads="150"
    scheme="https"
    secure="true"
    SSLEnabled="true"
    truststoreFile="/full/path/to/tomcat.keystore"
    truststorePass="(password)"
    keystoreFile="/full/path/to/tomcat.keystore"
    keystorePass="(password)"
    clientAuth="true"
    keyAlias="serverkey"
    sslProtocol="TLS"/>      

обратите внимание, что в приведенном выше XML-код:

  1. атрибут "port" может быть любым, что вы хотите.
  2. атрибуты "keystoreFile" и "truststoreFile" должны быть полными путями. Tomcat не выглядит в том же каталоге, что и сервер.XML по умолчанию.
  3. атрибуты "keystorePass" и "truststorePass" должны соответствовать значению (password), которое вы использовали при создании кот.файл keystore.
  4. атрибут "clientAuth"должны установите значение "true". Это то, что запускает взаимную аутентификацию.

кроме того, в сервера.xml, убедитесь, что вы НЕ иметь определенный AprLifecycleListner. XML для этого слушателя будет выглядеть примерно так:

<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

этот элемент должен быть удален / прокомментирован. AprLifecycleListener не настраивается таким же образом, как описано выше, и не будет работать с этими инструкциями.

перезапустить tomcat. Конфигурация сервера должна быть завершена.

я протестировал свою работу с помощью Firefox, потому что к нему легко добавить клиентские сертификаты. Откройте Firefox и попробуйте подключиться к конечной точке службы tomcat на порту, определенном в соединителе.

Ex: https://mytomcatdomain.com:8443/test

когда вы это сделаете, вы должны получить стандартное предупреждение от Firefox о ненадежном соединении, потому что мы создали самозаверяющий сертификат для нашего сервера Tomcat. Добавьте исключение для сертификата, чтобы наш клиент (Firefox) доверял нашему серверу (Tomcat).

как только вы добавили исключение, вы должны получить сообщение "безопасное соединение не удалось". Код ошибки - "ssl_error_bad_cert_alert". Это подтверждает, что наш сервер Tomcat запрашивает проверку подлинности клиента. Запрос не выполняется, потому что мы не настроили Firefox для отправки сертификата доверенного клиента еще.

чтобы настроить Firefox, нам нужно сделать немного больше магии:

// Create a file called DumpPrivateKey.java.  The contents should look like so:
public class DumpPrivateKey {
public static void main(String[] args) throws Exception {
  final String keystoreName = args[0];
    final String keystorePassword = args[1];
    final String alias = args[2];
    java.security.KeyStore ks = java.security.KeyStore.getInstance("jks");
    ks.load(new java.io.FileInputStream(keystoreName), keystorePassword.toCharArray());
    System.out.println("-----BEGIN PRIVATE KEY-----");
    System.out.println(new sun.misc.BASE64Encoder().encode(ks.getKey(alias, keystorePassword.toCharArray()).getEncoded()));
    System.out.println("-----END PRIVATE KEY-----");
  }
}

скомпилируйте файл java с помощью следующей команды:

javac DumpPrivateKey.java

теперь мы собираемся использовать эту небольшую утилиту для извлечения ключа из клиента.keystore файл мы создаем выше. Скопируйте клиента.keystore и клиента.файлы cer в том же каталоге, что и ваш класс DumpPrivateKey. Выполните следующие действия:

# This extracts the client key from the client keystore

java DumpPrivateKey client.keystore (password) clientkey > clientkey.pkcs8

# This creates a client.p12 file that can be used by Firefox

openssl pkcs12 -export -in client.cer -inkey clientkey.pkcs8 -password pass:(password) -out client.p12

обратите внимание, что в приведенном выше коде (пароль) должен быть пароль, который вы использовали для создания клиента.хранилище ключей.

Откройте настройки Firefox. Перейдите на вкладку "сертификаты". Нажмите на кнопку" Просмотреть сертификаты". Перейдите на вкладку "ваши сертификаты".

нажмите на кнопку "Импорт" и выберите "клиента.файл P12", который был создан ранее. Вам будет предложено ввести пароль для сертификата клиента.

если "клиент.p12 " был успешно импортирован, теперь вы можете обновить Страница Firefox, и вы должны получить успешный ответ от конечной точки сервера Tomcat.


@wbj, экспорт PrivateKeyEntry из JKS в PKCS #12 можно сделать намного проще:

keytool -importkeystore -srckeystore client.keystore -destkeystore client.p12 -deststoretype PKCS12 -srcalias client -deststorepass <password> -destkeypass <password>

Ура.


мне потребовалось некоторое время, чтобы заставить его работать правильно, используя сертификаты Openssl, составляя мои заметки, чтобы он мог помочь другим посетить эту страницу.

Шаг 1: Создайте свой собственный корневой CA

~/openssl$ mkdir -m 0700 /home/ubuntu/openssl/CA /home/ubuntu/openssl/CA/certs /home/ubuntu/openssl/CA/crl /home/ubuntu/openssl/CA/newcerts /home/ubuntu/openssl/CA/private
~/openssl$ touch /home/ubuntu/openssl/CA/indext.txt
~/openssl$ echo 1000 >> /home/ubuntu/openssl/CA/serial
~/openssl$ mv karun-tomcat-root-ca.key CA/private/

~/openssl$ sudo vi /etc/openssl.cnf
    # Make changes here
    dir = /home/ubuntu/openssl/CA
    #optionally change policy definitions as well
~/openssl$ openssl genrsa -des3 -out karun-tomcat-root-ca.key 2048

  #In below command make sure to use CN=<hostname of your machine>
~/openssl$ openssl req -new -x509 -days 36520 -key karun-tomcat-root-ca.key -out karun-tomcat-root-ca.crt -config openssl.cnf

~$ sudo cp ~/openssl/CA/certs/karun-tomcat-root-ca.crt /usr/share/ca-certificates/

  # make sure in the UI you enable/select the certificate created above
~$ sudo dpkg-reconfigure ca-certificates
  # Now reboot ubuntu machine just to make sure certificates are loaded successfully and tomcat picks it

Шаг 2: Создайте пару ключей сервера Tomcat

~$ openssl genrsa -out tomcat-server.key 2048

   # Use common name = <Give IP address>, department = Tomcat Server CSR
~$ openssl req -new -sha256 -config ~/openssl/openssl.cnf -key tomcat-server.key -out tomcat-server.csr
~$ openssl x509 -req -sha256 -days 36520 -in tomcat-server.csr -signkey tomcat-server.key -CA ~/openssl/CA/certs/karun-tomcat-root-ca.crt -CAkey ~/openssl/CA/private/karun-tomcat-root-ca.key -CAcreateserial -out tomcat-server.crt 
~$ openssl pkcs12 -export -name karun-tomcat-server-cert -in tomcat-server.crt -out tomcat-server.p12 -inkey tomcat-server.key -CAfile ~/openssl/CA/certs/karun-tomcat-root-ca.crt -caname karun-root -chain

~$ keytool -importkeystore -destkeystore tomcat-server.jks -srckeystore tomcat-server.p12 -srcstoretype pkcs12 -alias karun-tomcat-server-cert

~$ keytool -import -alias karun-root -keystore tomcat-server.jks -trustcacerts -file ~/openssl/CA/certs/karun-tomcat-root-ca.crt

# **(LATER)** Run this once client cert is generated
~$ keytool -importkeystore -alias karun-tomcat-client-cert -srckeystore ~/client-certs/tomcat-client.p12 -srcstoretype PKCS12 -destkeystore tomcat-server.jks -deststoretype JKS

# **(LATER)** Run this once tomcat server started successfully
~$ openssl s_client -connect localhost:8443 -cert ~/client-certs/tomcat-client.crt -key ~/client-certs/tomcat-client.key -debug -showcerts 

Шаг 3: Создайте Пару Ключей На Стороне Клиента

~$ openssl genrsa -out tomcat-client.key 2048
  # Use common name = <tomcat-user.xml's user say 'admin'>, department = Tomcat Client CSR
~$ openssl req -new -sha256 -config ~/openssl/openssl.cnf -key tomcat-client.key -out tomcat-client.csr
~$ openssl x509 -req -sha256 -days 36520 -in tomcat-client.csr -signkey tomcat-client.key -CA ~/openssl/CA/certs/karun-tomcat-root-ca.crt -CAkey ~/openssl/CA/private/karun-tomcat-root-ca.key -CAcreateserial -out tomcat-client.crt 
~$ openssl pkcs12 -export -name karun-tomcat-client-cert -in tomcat-client.crt -out tomcat-client.p12 -inkey tomcat-client.key -CAfile ~/openssl/CA/certs/karun-tomcat-root-ca.crt -caname karun-root -chain
~$ (optional step) keytool -importkeystore -destkeystore tomcat-client.jks -srckeystore tomcat-client.p12 -srcstoretype pkcs12 -alias karun-tomcat-client-cert
~$ (optional step) keytool -import -alias root -keystore tomcat-client.jks -trustcacerts -file ~/openssl/CA/certs/karun-tomcat-root-ca.crt

Шаг 4: Изменения Tomcat

# Make this change in server.xml of tomcat server
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
           keystoreFile="/opt/tomcat/openssl-certs/tomcat-server.jks"
           keystorePass="password"
           keyAlias="karun-tomcat-server-cert"
           truststoreFile="/opt/tomcat/openssl-certs/tomcat-server.jks"
           truststorePass="password"
           clientAuth="true" sslProtocol="TLS" />

Шаг 5: Перезагрузить Tomcat Server & & проверьте журналы, чтобы не допустить ошибок при загрузке

Шаг 6: загрузите сертификат клиента в браузер

в вашем браузере, например: firefox, перейдите в Настройки - > Дополнительно - > сертификат - > Просмотр сертификатов - > ваши сертификаты

импорт - кот-клиент.Р12"

https://<tomcat ip>:8443/

ссылки

http://pages.cs.wisc.edu / ~zmiller / ca-howto/

http://www.area536.com/projects/be-your-own-certificate-authority-with-openssl/


Я бы попробовал следующие действия

  1. Spool up контейнер, как вы настроили на 8443.
  2. запустите клиентское приложение с помощью-Djavax.сеть.debug=SSL

эта команда будет разматывать кучи информации. Что вам нужно проверить, так это то, что сервер представляет список ЦС, которые он примет для взаимной аутентификации. Если перечисленные CAs не содержат ваш сертификат, то клиент не будет иметь представления о том, как найти совпадение для сервера.

Это можно сделать намного проще с помощью команды openssl "s_client"

openssl s_client -connect localhost:8443 -showcerts

это отформатирует некоторую информацию, которая может быть неисчислима в их значении отладки этого.

если сервер не представляет список "приемлемых" CAs, вам придется сделать некоторую магию при создании набора сертификатов.

Дайте мне знать, что вы узнаете, и я могу, надеюсь, направить вас в правильном направлении направление.

OP добавлена дополнительная информация

Ok, поэтому для вас это немного проблема:

---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 263 bytes
---

две вещи выскакивают немедленно

  1. сервер не имеет однорангового сертификата
  2. в списке нет имен клиентских ЦС

для (1):

  1. убедитесь, что ваше хранилище ключей на самом деле имеет псевдоним "tomcat" в нем с помощью keytool.
  2. в хранить / пароль ключа в tomcat-это глупо. для благоразумия добавьте атрибуты keystorePassword и keyPassword в соединитель с одинаковыми значениями. The документация для Tomcat 7 указывает, что keystorePass будет по умолчанию для keyPass, если не установлен. Если ваш keyPass и keystorePass одинаковы, установите только атрибут keyPass.

теперь для (2) нам действительно нужно, чтобы (1) работал первым - так что получите это и работает, и мы увидим, где мы находимся этот момент.