在Websphere 8.0上使用JSSEHelper以编程方式指定出站SSL配置。不起作用

时间:2017-12-15 07:15:34

标签: ssl encryption websphere jsse outbound

我正在尝试使用在WAS 8.0.0.13(使用java 1.6.0的IBM Websphere应用程序服务器)中配置的CUSTOM出站ssl配置以编程方式创建SSL连接: (安全 - > SSL证书和密钥管理 - >相关项目:SSL配置)。 已成功创建安全连接:驻留在WAS服务器上的servlet已连接到侦听127.0.0.1:1234的服务器端套接字。 问题是我的首选密码套件是在“保护质量(QoP)设置”中定义的。 SSL配置中的内容将被忽略。 所有其他属性(例如协议或JSSE提供者)都被很好地看待。

我已经实现了一个Servlet,它是一个SSL客户端。 此Servlet使用此自定义SSL配置,该配置定义了以下密码套件:

  1. SSL_RSA_WITH_AES_128_CBC_SHA
  2. SSL_DHE_RSA_WITH_AES_128_CBC_SHA
  3. SSL_DHE_DSS_WITH_AES_128_CBC _
  4. SHA SSL_RSA_WITH_AES_128_GCM_SHA256
  5. SSL_RSA_WITH_AES_128_CBC_SHA256
  6. SSL_DHE_RSA_WITH_AES_128_GCM_SHA256
  7. SSL_DHE_RSA_WITH_AES_128_CBC_SHA256
  8. SSL_DHE_DSS_WITH_AES_128_GCM_SHA256
  9. SSL_DHE_DSS_WITH_AES_128_CBC_SHA256
  10. 不幸的是,ClientHello请求中提供了不同的密码套件列表:

    1. SSL_RSA_WITH_AES_128_CBC_SHA
    2. SSL_DHE_RSA_WITH_AES_128_CBC_SHA
    3. SSL_DHE_DSS_WITH_AES_128_CBC_SHA
    4. SSL_RSA_WITH_3DES_EDE_CBC_SHA
    5. SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
    6. SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
    7. SSL_RSA_WITH_DES_CBC_SHA
    8. SSL_DHE_RSA_WITH_DES_CBC_SHA
    9. SSL_DHE_DSS_WITH_DES_CBC_SHA
    10. SSL_RENEGO_PROTECTION_REQUEST
    11. (此自定义SSL配置在其定义中包含TLSv1.1协议。)

      我还尝试了另一种具有较小密码套件的协议(TLSv1.2):

      1. SSL_RSA_WITH_AES_128_CBC_SHA
      2. SSL_DHE_RSA_WITH_AES_128_CBC_SHA
      3. SSL_DHE_DSS_WITH_AES_128_CBC_SHA
      4. SSL_DHE_DSS_WITH_AES_128_CBC_SHA256
      5. ClientHello请求中再次提供了一个不同的密码套件列表:

        1. SSL_RSA_WITH_AES_128_CBC_SHA
        2. SSL_DHE_RSA_WITH_AES_128_CBC_SHA
        3. SSL_DHE_DSS_WITH_AES_128_CBC_SHA
        4. SSL_RSA_WITH_3DES_EDE_CBC_SHA
        5. SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
        6. 此外,我还检查了cell-default密码套件和node-default-cipher-suites,但没有 它们与ClientHello中提供的匹配: 默认节点配置/默认单元配置:

          1. SSL_RSA_WITH_AES_128_CBC_SHA
          2. SSL_DHE_RSA_WITH_AES_128_CBC_SHA
          3. SSL_DHE_DSS_WITH_AES_128_CBC_SHA
          4. SSL_RSA_WITH_AES_128_GCM_SHA256
          5. SSL_RSA_WITH_AES_128_CBC_SHA256
          6. SSL_DHE_RSA_WITH_AES_128_GCM_SHA256
          7. SSL_DHE_RSA_WITH_AES_128_CBC_SHA256
          8. SSL_DHE_DSS_WITH_AES_128_GCM_SHA256
          9. SSL_DHE_DSS_WITH_AES_128_CBC_SHA256
          10. 我已按照以下说明操作: 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的存在似乎并不重要。 无论是设置为null还是不包含任何值都无关紧要。

            我还尝试在线程上强制执行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);
            }
            

            最后,我尝试不绑定到WAS服务器SSL配置中的任何SSL配置,但只使用我的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 个答案:

答案 0 :(得分:1)

因为我最初没有仔细查看你的代码。我看到了问题。因为您直接从JSSEHelper获取Socket工厂,所以我们没有机会将密码放在套接字上。

在您的情况下,您应该遵循WAS的编程SSL方法。获取属性并将它们放在线程上。例如

cout

后者没有从JSSE获得Socket工厂,获得默认值。所以在getSslSocket()中执行类似的操作:

 try {
        String existingAlias = "TLSv1.1";
        existing_sslProps = jsseHelper.getProperties(existingAlias);
    jsseHelper.setSSLPropertiesOnThread(existing_sslProps);

    } catch (com.ibm.websphere.ssl.SSLException e) {
        e.printStackTrace();
    } 

这将为您提供WAS套接字工厂。创建套接字调用应该返回一个套接字,其中包含在SSLSocket上设置的密码。完成后,您应该清除线程​​中的属性。

public SSLSocket getSslSocket(Properties sslProps) {

    SSLSocketFactory factory = SSLSocketFactory.getDefault();

    SSLSocket socket = null;
    try {
        socket = (SSLSocket) factory.createSocket();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return socket;
}

答案 1 :(得分:0)

谢谢你的提示!我按照这些说明操作:

https://www-01.ibm.com/support/docview.wss?uid=swg21162961

根据您的提示增加日志/跟踪级别。 如果我必须更改其他配置,请告诉我。

我只收集了这些子目录中的日志文件:

  1. ../日志/ server1的
  2. ../日志/节点代理
  3. ../日志/ FFDC 并将它们放在这些文件中的ALL_LOGS / logs目录中:
  4. 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

    我不确定是否是我的问题的根本原因,但谷歌搜索结果似乎与我的问题无关。 就谷歌的结果而言,我的意思是:

    https://www.ibm.com/developerworks/community/forums/html/topic?id=a2910c33-8f55-4ef7-823d-7ae367682e35

    http://www.dsxchange.com/viewtopic.php?t=134492&sid=f6e236a4f14a9d80fc51c0820e5f7ce7 他们都没有帮助......

    与logs-subdirectories一起,我还在TLSv1.1_enforce_OnThread.log中附加了stderr的服务器端套接字stdout。 另外,我还附加了客户端配置CONFIG_TLSv1.1._ENFORSE_SSL_ON_THREAD.png

    您能检查一下这些日志文件吗? 老实说,非常感谢你。

    - 迈克尔

答案 2 :(得分:0)

我正在查看涉及使用名为“TLSv1.1”的SSL配置的错误。 TLSv1.1不支持您配置的3个密码中的2个,您可以在此处找到有关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] 

此连接将在同一主机127.0.0.1上发送到端口9202。并最终以错误结束,javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure。我认为您的服务器正在尝试使用错误的SSL配置与您的nodeagent通信。它似乎从动态出站选择过滤器中选择了该配置。

[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的任何内容,以使用名为“TLSv1.1”的SSL配置。这种连接似乎正在使用TLSv1协议。因此,由于协议不匹配,连接失败。看来这个SSL配置不打算用于访问127.0.0.1和端口9202.这可能是您的本地节点代理还是dmgr端口?如果是这样,连接需要NodeDefaultSSLSettings。

在跟踪中,与您的服务器,localhost和端口1234进行通信的连接并不明显。或许,如果您修改了配置,以便在转到端口9202和127.0.0.1时节点将使用正确的SSL配置可能更容易理解。

答案 3 :(得分:0)

感谢您的大力支持和支持机智的回复! 根据您的输入,我删除了SSL配置设置中存在的所有动态出站规则。

我还修改了支持的密码套件列表 在WAS端(客户端)基于您提供的很棒的链接!:-)。 更确切地说,我选择了这些套房 因为所有TLS协议(TLSv1.0,TLSv1.1,TLSv1.2)都支持它们:

  1. SSL_RSA_WITH_AES_128_CBC_SHA
  2. SSL_RSA_WITH_3DES_EDE_CBC_SHA
  3. SSL_DHE_RSA_WITH_AES_128_CBC_SHA
  4. SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
  5. SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
  6. 再次,我清除了所有日志文件,然后启动了应用程序服务器。 重新测试我的方案后,已生成日志文件中的此增量: https://drive.google.com/open?id=19KaDlsx2UVS_YfByaORQOf89mLlJke4e

    侦听1234端口的服务器端应用程序支持相同 密码套件:

    1. SSL_RSA_WITH_AES_128_CBC_SHA
    2. SSL_RSA_WITH_3DES_EDE_CBC_SHA
    3. SSL_DHE_RSA_WITH_AES_128_CBC_SHA
    4. SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
    5. SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
    6. 当然,我没想到在这些变化之后问题会得到解决 但我希望我在日志/跟踪中发现一些错误,以减轻你的负担。不幸的是,我没有成功。你能检查一下这些日志/痕迹吗?老实说,非常感谢你!

      (请忽略此例外:

      FFDC异常:java.net.MalformedURLException SourceId:class com.ibm.wkplc.extensionregistry.PluginDescriptor.initFromDom ProbeId:1

      出现在server1_b7f67871_17.12.19_04.44.51.8551967663872103714940.txt文件中, 因为我再次重新测试了它(第3次),并且在第3次重新测试后没有出现这种异常。)