Указание исходящей конфигурации SSL программно с использованием JSSEHelper на Websphere 8.0. не работает
Я пытаюсь создать SSL-соединение программно с использованием исходящей конфигурации ssl CUSTOM, настроенной в WAS 8.0.0.13 (сервер приложений IBM Websphere, использующий java 1.6.0): (Безопасность-> Управление сертификатом SSL и ключами-> Связанные элементы: Конфигурации SSL). Защищенное соединение успешно создано: сервлет, находящийся на сервере WAS, подключился к сокету на стороне сервера, прослушивающему 127.0.0.1:1234. Проблема заключается в том, что мои предпочтительные комплекты шифров, определенные в "Настройках качества защиты (QoP)" в конфигурации SSL, игнорируются. Все остальные свойства (такие как протокол или поставщик JSSE) хорошо рассматриваются.
Я реализовал сервлет, который был в роли SSL-клиента. Этот сервлет использовал эту пользовательскую конфигурацию SSL, в которой были определены следующие наборы шифров:
- SSL_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_DSS_WITH_AES_128_CBC_
- SHA SSL_RSA_WITH_AES_128_GCM_SHA256
- SSL_RSA_WITH_AES_128_CBC_SHA256
- SSL_DHE_RSA_WITH_AES_128_GCM_SHA256
- SSL_DHE_RSA_WITH_AES_128_CBC_SHA256
- SSL_DHE_DSS_WITH_AES_128_GCM_SHA256
- SSL_DHE_DSS_WITH_AES_128_CBC_SHA256
К сожалению, другой список комплектов шифров был предоставлен в запросе ClientHello:
- SSL_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_DSS_WITH_AES_128_CBC_SHA
- SSL_RSA_WITH_3DES_EDE_CBC_SHA
- SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
- SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
- SSL_RSA_WITH_DES_CBC_SHA
- SSL_DHE_RSA_WITH_DES_CBC_SHA
- SSL_DHE_DSS_WITH_DES_CBC_SHA
- SSL_RENEGO_PROTECTION_REQUEST
(Эта пользовательская конфигурация SSL содержала протокол TLSv1.1 в своем определении.)
Я также попробовал другой протокол (TLSv1.2) с меньшим набором наборов шифров:
- SSL_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_DSS_WITH_AES_128_CBC_SHA
- SSL_DHE_DSS_WITH_AES_128_CBC_SHA256
Еще раз, другой список наборов шифров был предоставлен в запросе ClientHello:
- SSL_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_DSS_WITH_AES_128_CBC_SHA
- SSL_RSA_WITH_3DES_EDE_CBC_SHA
- SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
Кроме того, я также проверил наборы шифров по умолчанию для ячеек и наборы узлов по умолчанию, и нет совпадения между ними и теми, которые указаны в ClientHello: Конфигурация узла по умолчанию / Конфигурация ячейки по умолчанию:
- SSL_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_DSS_WITH_AES_128_CBC_SHA
- SSL_RSA_WITH_AES_128_GCM_SHA256
- SSL_RSA_WITH_AES_128_CBC_SHA256
- SSL_DHE_RSA_WITH_AES_128_GCM_SHA256
- SSL_DHE_RSA_WITH_AES_128_CBC_SHA256
- SSL_DHE_DSS_WITH_AES_128_GCM_SHA256
- SSL_DHE_DSS_WITH_AES_128_CBC_SHA256
Я следовал этим инструкциям: https://www.ibm.com/support/knowledgecenter/en/SSAW57_8.0.0/com.ibm.websphere.nd.doc/info/ae/ae/tsec_ssloutconfiguseJSSE.html
и создали следующую реализацию. Метод doGet является точкой входа:
public class TLSv1_1 extends HttpServlet {
private static final long serialVersionUID = 1L;
com.ibm.websphere.ssl.JSSEHelper jsseHelper;
public TLSv1_1() {
super();
jsseHelper = com.ibm.websphere.ssl.JSSEHelper.getInstance();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Properties existing_sslProps = null;
try {
String existingAlias = "TLSv1.1";
existing_sslProps = jsseHelper.getProperties(existingAlias);
} catch (com.ibm.websphere.ssl.SSLException e) {
e.printStackTrace();
}
printSSLproperties(response, existing_sslProps);
SSLSocket socket = getSslSocket(existing_sslProps);
writeToSocket(socket, 1234);
}
public static void printSSLproperties(HttpServletResponse response, Properties sslProps) throws IOException {
if (sslProps != null) {
StringBuilder sb = new StringBuilder();
Set set = sslProps.entrySet();
Iterator it = set.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
Object value = entry.getValue();
sb.append("key: " + entry.getKey() + ", value: " + value + "\n");
}
System.out.println("sslProps: -----------\n" + sb.toString());
} else {
System.out.println("sslProps == null");
response.getWriter().append("sslProps == null");
}
}
public SSLSocket getSslSocket(Properties sslProps) {
Map<String, Object> sslMap = new HashMap<String, Object>();
sslMap.put("com.ibm.ssl.direction", "outbound");
sslMap.put("com.ibm.ssl.remoteHost", "127.0.0.1");
sslMap.put("com.ibm.ssl.remotePort", "1234");
sslMap.put("com.ibm.ssl.endPointName", "HTTP");
SSLSocketFactory sslSocketFactory = null;
try {
sslSocketFactory = jsseHelper.getSSLSocketFactory(sslMap, sslProps);
} catch (SSLException e) {
e.printStackTrace();
}
SSLSocket socket = null;
try {
socket = (SSLSocket) sslSocketFactory.createSocket();
} catch (IOException e) {
e.printStackTrace();
}
return socket;
}
public static void writeToSocket(Socket socket, int port) throws IOException, UnknownHostException {
InetAddress address = InetAddress.getByName("127.0.0.1");
socket.connect(new InetSocketAddress(address, port));
BufferedWriter stream = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
for (int i = 0; i < 3; i++) {
String lineX = UUID.randomUUID().toString();
stream.write(lineX);
stream.newLine();
stream.flush();
System.out.println("NEW LINE SUCCESSFULLY WRITTEN INTO SOCKET:" + lineX);
sleep();
}
}
private static void sleep() {
try {
Thread.sleep(1000 * 30);
} catch (InterruptedException e) {
}
}
}
Наличие хэш-карты sslMap, похоже, не имеет значения. Не имеет значения, установлено ли значение в ноль или не содержит значений.
Я также попытался применить свойства ssl в потоке (этот метод имеет наибольшее предпочтение среди всех остальных): этот подход также не сработал:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String existingAlias = "TLSv1.1";
existing_sslProps = jsseHelper.getProperties(existingAlias);
jsseHelper.setSSLPropertiesOnThread(existing_sslProps);
CommonIO.printSSLproperties(response, existing_sslProps);
SSLSocket socket = getSslSocket(existing_sslProps);
CommonIO.writeToSocket(socket, 1234);
jsseHelper.setSSLPropertiesOnThread(null);
}
Наконец, я попытался не привязывать ни одну конфигурацию SSL, присутствующую в конфигурациях SSL WAS-сервера, а только соединить пользовательскую конфигурацию с моим Java-кодом:
sslProps.setProperty("com.ibm.ssl.protocol", "TLSv1.1");
sslProps.setProperty("com.ibm.ssl.enabledCipherSuites",
"SSL_DHE_DSS_WITH_AES_128_CBC_SHA SSL_DHE_DSS_WITH_AES_128_GCM_SHA256 SSL_DHE_DSS_WITH_AES_128_CBC_SHA256");
sslProps.setProperty("com.ibm.ssl.trustStore",
"/opt/IBM/Websphere/profiles/AppSrv01/config/cells/localhostCell01/nodes/localhostNode01/trust.p12");
sslProps.setProperty("com.ibm.ssl.trustStorePassword", "***");
sslProps.setProperty("com.ibm.ssl.trustStoreType", "PKCS12");
sslProps.setProperty("com.ibm.ssl.keyStore",
"/opt/IBM/Websphere/profiles/AppSrv01/config/cells/localhostCell01/key.p12");
sslProps.setProperty("com.ibm.ssl.keyStorePassword", "***");
sslProps.setProperty("com.ibm.ssl.keyStoreType", "PKCS12");
sslProps.setProperty("security.provider.1", "com.ibm.jsse2.IBMJSSEProvider2");
sslProps.setProperty("ssl.SocketFactory.provider", "com.ibm.jsse2.SSLSocketFactoryImpl");
Но этот подход также не сработал. Не могли бы вы мне помочь? Я предполагаю, что пропустил что-то основное или пользовательская конфигурация SSL не существует в этом продукте.
4 ответа
Так что из-за того, что я не смотрю на ваш код внимательно изначально. Я вижу проблему. Поскольку вы получаете фабрику сокетов непосредственно от JSSEHelper, у нас нет возможности поставить шифры на сокет.
В вашем случае вы должны следовать программным методам SSL WAS. Получите свойства и поместите их в поток. например
try {
String existingAlias = "TLSv1.1";
existing_sslProps = jsseHelper.getProperties(existingAlias);
jsseHelper.setSSLPropertiesOnThread(existing_sslProps);
} catch (com.ibm.websphere.ssl.SSLException e) {
e.printStackTrace();
}
Позднее не получите фабрику сокетов от JSSE, получите значение по умолчанию. Так что в getSslSocket() сделать что-то вроде:
public SSLSocket getSslSocket(Properties sslProps) {
SSLSocketFactory factory = SSLSocketFactory.getDefault();
SSLSocket socket = null;
try {
socket = (SSLSocket) factory.createSocket();
} catch (IOException e) {
e.printStackTrace();
}
return socket;
}
Это даст вам фабрику розеток WAS. Вызов create socket должен вернуть вам сокет с установленными на SSLSocket шифрами. Когда вы закончите, вы должны удалить свойства из потока.
jsseHelper.setSSLPropertiesOnThread(null);
Я смотрю на ошибку, связанную с использованием конфигурации SSL с именем "TLSv1.1". 2 из 3 настроенных вами шифров не поддерживаются TLSv1.1, более подробную информацию о шифре, поддерживаемом IBM java 6, вы можете найти здесь https://www.ibm.com/support/knowledgecenter/es/SSYKE2_6.0.0/com.ibm.java.security.component.60.doc/security-component/jsse2Docs/ciphersuites.html?view=embed. Это оставляет вас с одним шифром, SSL_DHE_DSS_WITH_AES_128_CBC_SHA.
[12/17/17 6:16:19:524 EST] 00000000 SystemOut O Ignoring unsupported cipher suite: SSL_DHE_DSS_WITH_AES_128_GCM_SHA256
[12/17/17 6:16:19:524 EST] 00000000 SystemOut O Ignoring unsupported cipher suite: SSL_DHE_DSS_WITH_AES_128_CBC_SHA256
[12/17/17 6:16:19:527 EST] 00000000 SystemOut O %% No cached client session
[12/17/17 6:16:19:528 EST] 00000000 SystemOut O *** ClientHello, TLSv1.1
[12/17/17 6:16:19:528 EST] 00000000 SystemOut O RandomCookie: GMT: 1513509379 bytes = { 108, 16, 192, 144, 124, 116, 226, 48, 69, 61, 93, 187, 104, 67, 120, 166, 233, 194, 67, 244, 136, 159, 105, 130, 106, 175, 18, 251 }
[12/17/17 6:16:19:529 EST] 00000000 SystemOut O Session ID: {}
[12/17/17 6:16:19:529 EST] 00000000 SystemOut O Cipher Suites: [SSL_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RENEGO_PROTECTION_REQUEST]
Это соединение идет к порту 9202 на том же хосте, 127.0.0.1. И в конечном итоге заканчивается ошибка, javax.net.ssl.SSLHandshakeException: получено фатальное предупреждение: handshake_failure. Я думаю, что ваш сервер пытается связаться с вашим агентом узла с неправильной конфигурацией SSL. Кажется, эта конфигурация выбрана из фильтра динамического выбора исходящих сообщений.
[12/17/17 6:16:19:440 EST] 00000000 SSLConfigMana 3 SSLConfig dynamic selection info: *,127.0.0.1,*
[12/17/17 6:16:19:440 EST] 00000000 SSLConfigMana 3 Parsing entry 0 of 1: *,127.0.0.1,*
[12/17/17 6:16:19:440 EST] 00000000 SSLConfigMana 3 This entry has 3 attributes.
[12/17/17 6:16:19:440 EST] 00000000 SSLConfigMana 3 Protocol: *, Host: 127.0.0.1, Port: *
[12/17/17 6:16:19:440 EST] 00000000 SSLConfigMana 3 Found a dynamic selection match!
[12/17/17 6:16:19:440 EST] 00000000 SSLConfigMana < getPropertiesFromDynamicSelectionInfo -> found. Exit
Ваш фильтр будет соответствовать чему-либо, идущему к 127.0.0.1, чтобы использовать конфигурацию SSL под названием "TLSv1.1". Кажется, что это соединение использует протокол TLSv1. Таким образом, соединение не удается из-за несоответствия протокола. Кажется, эта конфигурация SSL не предназначена для использования с доступом к 127.0.0.1 и порту 9202. Может ли это быть агент локального узла или порт dmgr? Если это так, соединение должно быть связано с NodeDefaultSSLSettings.
Для меня не очевидно, что соединение говорит с вашим сервером, локальным хостом и портом 1234. Возможно, если вы исправите свою конфигурацию так, чтобы узел использовал правильную конфигурацию SSL при переходе на порт 9202 и 127.0.0.1, это может быть проще выяснить.
Спасибо за ваши советы! Я следовал этим инструкциям:
https://www-01.ibm.com/support/docview.wss?uid=swg21162961
увеличить уровень журнала / трассировки на основе ваших советов. Если я должен был сделать некоторые другие изменения конфигурации, пожалуйста, дайте мне знать.
Я собрал файлы журналов только из этих подкаталогов:
- ../logs/server1
- ../logs/nodeagent
- ../logs/ffdc и поместил их в каталог ALL_LOGS/logs в этих файлах:
https://drive.google.com/open?id=18TMYyjKx8L_pd8TxFG1uq1rOmikVyWeg
, так что, если есть и другие файлы журнала / трассировки в разных местах, пожалуйста, дайте мне знать. (В этих файлах присутствует только Delta, поскольку я очистил все файлы журнала / трассировки перед запуском сервера и повторным тестированием сценария.)
Я нашел только это в логах ffdc:
The client and server could not negotiate the desired level of security.Reason: Received fatal alert: handshake_failure vmcid: 0x49421000 minor code: 70 completed: No
Я не уверен, является ли коренная причина моей проблемы, но никакие результаты Google, казалось, не относились к моей проблеме. Что касается результатов Google, я имел в виду следующее:
http://www.dsxchange.com/viewtopic.php?t=134492&sid=f6e236a4f14a9d80fc51c0820e5f7ce7 Ни один из них не помог...
Наряду с подкаталогами log-файлов я также присоединяю стандартный вывод сокета сервера со stderr в TLSv1.1_enforce_OnThread.log. Кроме того, я также прилагаю конфигурацию на стороне клиента CONFIG_TLSv1.1._ENFORSE_SSL_ON_THREAD.png
Не могли бы вы проверить эти файлы журнала? Спасибо, честно, большое.
-- Майкл
Спасибо за вашу большую поддержку и быстрый ответ! основываясь на ваших входных данных, я удалил все динамические исходящие правила, присутствующие в настройках конфигурации SSL.
Я также изменил список поддерживаемых наборов шифров на стороне WAS (на стороне клиента) на основе предоставленной вами отличной ссылки!:-). Точнее, я выбрал только эти комплекты, потому что они поддерживаются всеми протоколами TLS (TLSv1.0, TLSv1.1, TLSv1.2):
- SSL_RSA_WITH_AES_128_CBC_SHA
- SSL_RSA_WITH_3DES_EDE_CBC_SHA
- SSL_DHE_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
- SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
Я снова очистил все файлы журнала и запустил сервер приложений. После повторного тестирования моего сценария эта дельта в лог-файлах была сгенерирована: https://drive.google.com/open?id=19KaDlsx2UVS_YfByaORQOf89mLlJke4e
Серверное приложение, которое прослушивает порт 1234, поддерживает те же наборы шифров:
- SSL_RSA_WITH_AES_128_CBC_SHA
- SSL_RSA_WITH_3DES_EDE_CBC_SHA
- SSL_DHE_RSA_WITH_AES_128_CBC_SHA
- SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
- SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
Конечно, я не ожидал, что проблема будет решена после этих изменений, но я ожидал, что я найду некоторые ошибки в журналах / трассировках, чтобы уменьшить нагрузку на вас. К сожалению, мне не удалось. Не могли бы вы проверить эти журналы / следы? Спасибо, честно, большое спасибо!
(Пожалуйста, игнорируйте это исключение:
Исключение FFDC:java.net.MalformedURLException SourceId: класс com.ibm.wkplc.extensionregistry.PluginDescriptor.initFromDom ProbeId:1
присутствует в файле server1_b7f67871_17.12.19_04.44.51.8551967663872103714940.txt, так как я еще раз проверил его (в третий раз), и это исключение не появилось после 3-го повторного тестирования.)