jjzjj

java - Jetty 日志中的 SSL_NULL_WITH_NULL_NULL 密码套件

coder 2024-03-25 原文

我正在使用带有 HTTPS 和有效证书的 Jetty,但我不确定它是否正确,因为服务器日志中的密码套件似乎是 SSL_NULL_WITH_NULL_NULL。然而,客户端日志看起来不错。

长话短说:我附上了一个需要 Jetty-7.6.10 的 Java 示例和两个用于创建 keystore 和信任库的脚本。

JettyHttpsForStackOverflow 同时或单独运行客户端和服务器以去复杂化日志。

create-chains.sh 脚本创建 keystore 和信任库。 keystore 包含一个由临时 keystore 生成的根证书颁发机构结尾的链。它使用证书颁发机构和中间证书复制真实案例。

create-single-autosigned.sh 脚本也创建 keystore 和信任库,但使用自签名证书。

请注意,SSL_NULL_WITH_NULL_NULL 显示为具有两个证书链的服务器密码套件。

我觉得服务器域名没有问题。对于在域名与正确签名证书中的专有名称匹配的机器上运行的服务器,我遇到了同样的问题。 SSLLab 确认我的服务器上的 SSL 工作正常(B 级),并且 Google Chrome 可以愉快地连接。

我觉得Jetty客户端没有问题。当我使用它时,它只是调用我正在设置的 SSLContextFactory 来创建一个 SSLSocket。令人惊讶的是,在 Jetty 客户端日志中,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 似乎是正在使用的密码套件。

在 Jetty 服务器日志中获取 SSL_NULL_WITH_NULL_NULL 是否正常?如果不是,如何正确处理?

create-single-autosigned.sh

#!/bin/bash

rm  their-keystore.jks 2> /dev/null
rm  my-keystore.jks    2> /dev/null
rm  my-truststore.jks  2> /dev/null

echo "===================================================="
echo "Creating fake third-party chain ca2 -> ca1 -> ca ..."
echo "===================================================="

keytool -genkeypair -alias ca  -dname cn=ca                           \
  -validity 10000 -keyalg RSA -keysize 2048                           \
  -ext BasicConstraints:critical=ca:true,pathlen:10000                \
  -keystore their-keystore.jks -keypass Keypass -storepass Storepass

keytool -genkeypair -alias ca1 -dname cn=ca1                          \
  -validity 10000 -keyalg RSA -keysize 2048                           \
  -keystore their-keystore.jks -keypass Keypass -storepass Storepass

keytool -genkeypair -alias ca2 -dname cn=ca2                          \
  -validity 10000 -keyalg RSA -keysize 2048                           \
  -keystore their-keystore.jks -keypass Keypass -storepass Storepass


  keytool -certreq -alias ca1                                            \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass   \
| keytool -gencert -alias ca                                             \
    -ext KeyUsage:critical=keyCertSign                                   \
    -ext SubjectAlternativeName=dns:ca1                                  \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass   \
| keytool -importcert -alias ca1                                         \
    -keystore   their-keystore.jks -keypass Keypass -storepass Storepass

#echo "Debug exit" ; exit 0

  keytool -certreq -alias ca2                                           \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass  \
| keytool -gencert -alias ca1                                           \
    -ext KeyUsage:critical=keyCertSign                                  \
    -ext SubjectAlternativeName=dns:ca2                                 \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass  \
| keytool -importcert -alias ca2                                        \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass

keytool -list -v -storepass Storepass -keystore their-keystore.jks


echo  "===================================================================="
echo  "Fake third-party chain generated. Now generating my-keystore.jks ..."
echo  "===================================================================="
read -p "Press a key to continue."

# Import authority's certificate chain

  keytool -exportcert -alias ca                                         \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass  \
| keytool -importcert -trustcacerts -noprompt -alias ca                 \
    -keystore  my-keystore.jks -keypass Keypass -storepass Storepass

  keytool -exportcert -alias ca1                                        \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass  \
| keytool -importcert -noprompt -alias ca1                              \
    -keystore  my-keystore.jks -keypass Keypass -storepass Storepass

  keytool -exportcert -alias ca2                                        \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass  \
| keytool -importcert -noprompt -alias ca2                              \
    -keystore  my-keystore.jks -keypass Keypass -storepass Storepass

# Create our own certificate, the authority signs it.

keytool -genkeypair -alias e1  -dname cn=e1                        \
  -validity 10000 -keyalg RSA -keysize 2048                        \
  -keystore my-keystore.jks -keypass Keypass -storepass Storepass

  keytool -certreq -alias e1                                            \
    -keystore my-keystore.jks -keypass Keypass -storepass Storepass     \
| keytool -gencert -alias ca2                                           \
    -ext SubjectAlternativeName=dns:localhost,ip:127.0.0.1              \
    -ext KeyUsage:critical=keyEncipherment,digitalSignature             \
    -ext ExtendedKeyUsage=serverAuth,clientAuth                         \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass  \
| keytool -importcert -alias e1                                         \
    -keystore my-keystore.jks -keypass Keypass -storepass Storepass

keytool -list -v  -storepass Storepass -keystore  my-keystore.jks

echo "================================================="
echo "Keystore generated. Now generating truststore ..."
echo "================================================="
read -p "Press a key to continue."

  keytool -exportcert -alias ca                                        \
    -keystore my-keystore.jks -keypass Keypass -storepass Storepass    \
| keytool -importcert -trustcacerts -noprompt -alias ca                \
    -keystore my-truststore.jks -keypass Keypass -storepass Storepass

  keytool -exportcert -alias ca1                                       \
    -keystore my-keystore.jks -keypass Keypass -storepass Storepass    \
| keytool -importcert -noprompt -alias ca1                             \
    -keystore my-truststore.jks -keypass Keypass -storepass Storepass

  keytool -exportcert -alias ca2                                       \
    -keystore my-keystore.jks -keypass Keypass -storepass Storepass    \
| keytool -importcert -noprompt -alias ca2                             \
    -keystore my-truststore.jks -keypass Keypass -storepass Storepass

  keytool -exportcert -alias e1                                        \
    -keystore my-keystore.jks -keypass Keypass -storepass Storepass    \
| keytool -importcert -noprompt -alias e1                              \
    -keystore my-truststore.jks -keypass Keypass -storepass Storepass

keytool -list -v  -storepass Storepass -keystore  my-truststore.jks

rm  their-keystore.jks 2> /dev/null

create-single-autosigned.sh

#!/bin/bash

rm  my-keystore.jks    2> /dev/null
rm  my-truststore.jks  2> /dev/null

keytool -genkeypair -alias e1  -dname cn=e1                        \
  -validity 10000 -keyalg RSA -keysize 2048                        \
  -keystore my-keystore.jks -keypass Keypass -storepass Storepass



keytool -list -v  -storepass Storepass -keystore  my-keystore.jks

echo "================================================="
echo "Keystore generated. Now generating truststore ..."
echo "================================================="
read -p "Press a key to continue."

  keytool -exportcert -alias e1                                        \
    -keystore my-keystore.jks -keypass Keypass -storepass Storepass    \
| keytool -importcert -noprompt -alias e1                              \
    -keystore my-truststore.jks -keypass Keypass -storepass Storepass

keytool -list -v  -storepass Storepass -keystore  my-truststore.jks

JettyHttpsForStackOverflow.java

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import org.eclipse.jetty.client.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;


/**
 * Code sample for Jetty {@link HttpClient} with HTTPS, in a completely standalone fashion.
 * Use create-chains.sh and create-empty.sh to generate completely standalone certificates.
 */
public class JettyHttpsForStackOverflow {

  public static void main( final String... arguments ) throws Exception {
    System.setProperty( "javax.net.debug", "all" ) ;

    try {
      if( arguments.length == 0 || "server".equals( arguments[ 0 ] ) ) {
        runServer() ;
      }
      if( arguments.length == 0 || "client".equals( arguments[ 0 ] ) ) {
        runClient() ;
      }
    } catch( Exception e ) {
      e.printStackTrace() ;
      System.exit( 1 ) ; // Avoids keeping the port open.
    }

  }

  private static void runServer() throws Exception {
    final KeyStore keyStore = loadKeystore() ;
    final SSLContext sslContext = createSslContext(
        keyStore,
        KEYPASS,
        newTrustManagers( keyStore, CERTIFICATE_ALIAS )
    ) ;

    final SslContextFactory sslContextFactory = new SslContextFactory() {
      @Override
      public SSLEngine newSslEngine() {
        return sslContext.createSSLEngine() ;
      }
      @Override
      public SSLEngine newSslEngine( final String host, final int port ) {
        return sslContext.createSSLEngine( host, port ) ;
      }
    } ;
    sslContextFactory.setAllowRenegotiate( true ) ;
    sslContextFactory.setNeedClientAuth( false ) ;
    sslContextFactory.setWantClientAuth( false ) ;
    sslContextFactory.setKeyStorePath( keyStore.toString() ) ; // Better logging.
    sslContextFactory.setKeyStore( keyStore ) ;
    sslContextFactory.setCertAlias( CERTIFICATE_ALIAS ) ;
    sslContextFactory.setKeyManagerPassword( KEYPASS ) ;

    final SslSelectChannelConnector sslConnector =
        new SslSelectChannelConnector( sslContextFactory ) ;
    sslConnector.setPort( PORT ) ;
    sslConnector.open() ;

    final Server jettyServer = new Server() ;
    jettyServer.addConnector( sslConnector ) ;

    jettyServer.start() ;
  }

  public static void runClient() throws Exception {
    final KeyStore keyStore = loadTruststore() ;

    final HttpClient httpClient = new HttpClient() ;
    httpClient.getSslContextFactory().setKeyStore( keyStore ) ; // Better logging.
    httpClient.getSslContextFactory().setKeyStorePassword( "storepwd" ) ;
    httpClient.getSslContextFactory().setKeyManagerPassword( KEYPASS ) ;
    httpClient.setConnectorType( HttpClient.CONNECTOR_SELECT_CHANNEL ) ;
    httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET);


    // Don't need that because shipping our own certificate in the truststore.
    // Anyways, it blows when set to true.
//    httpClient.getSslContextFactory().setValidateCerts( false ) ;

    httpClient.start() ;

    final ContentExchange contentExchange = new ContentExchange() ;
    contentExchange.setURI( new URL( "https://localhost:" + PORT ).toURI() ) ;
    contentExchange.setTimeout( 36_000_000 ) ; // Leave time for debugging.
    httpClient.send( contentExchange ) ;
    contentExchange.waitForDone() ;
    assert( contentExchange.getStatus() == ContentExchange.STATUS_COMPLETED ) ;
  }

  private static SSLContext createSslContext(
      final KeyStore keyStore,
      final String keypass,
      final TrustManager[] trustManagers
  ) {
    try {
      final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( "SunX509" ) ;
      keyManagerFactory.init( keyStore, keypass == null ? null : keypass.toCharArray() ) ;
      final KeyManager[] keyManagers = keyManagerFactory.getKeyManagers() ;
      final SecureRandom secureRandom = new SecureRandom() ;

      final SSLContext sslContext = SSLContext.getInstance( "TLS" ) ;
      sslContext.init(
          keyManagers,
          trustManagers,
          secureRandom
      ) ;
      return sslContext ;
    } catch( NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException
        | KeyManagementException e
    ) {
      throw new RuntimeException( e ) ;
    }
  }



  private static TrustManager[] newTrustManagers(
      final KeyStore keyStore,
      final String certificateAlias
  ) {
    try {
      final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( "SunX509" ) ;
      trustManagerFactory.init( keyStore ) ;
      final TrustManager[] trustManagers ;
      if( certificateAlias == null ) {
        trustManagers = trustManagerFactory.getTrustManagers() ;
      } else {
        final Certificate certificate = keyStore.getCertificate( certificateAlias ) ;
        final X509Certificate[] x509Certificates ;
        if( certificate == null ) {
          x509Certificates = new X509Certificate[ 0 ] ;
        } else {
          x509Certificates = new X509Certificate[] { ( X509Certificate ) certificate } ;
        }
        trustManagers = new TrustManager[] { newX509TrustManager( x509Certificates ) } ;

      }
      return trustManagers ;
    } catch( KeyStoreException | NoSuchAlgorithmException e ) {
      throw new RuntimeException( e );
    }

  }

  private static final TrustManager newX509TrustManager( final X509Certificate[] certificates ) {
    return new X509TrustManager() {

      public X509Certificate[] getAcceptedIssuers() {
        return certificates ;
      }

      public void checkClientTrusted(
          final X509Certificate[] certs,
          final String authType
      ) { ; }

      public void checkServerTrusted(
          final X509Certificate[] certs,
          final String authType
      ) { ; }
    } ;
  }


  public static KeyStore loadKeystore()
      throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException
  {
    return loadKeystore( KEYSTORE_RESOURCE_URL ) ;
  }

  public static KeyStore loadTruststore()
      throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException
  {
    return loadKeystore( TRUSTSTORE_RESOURCE_URL ) ;
  }

  public static KeyStore loadKeystore( final URL keystoreResourceUrl )
      throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException
  {
    try( final InputStream inputStream = keystoreResourceUrl.openStream() ) {
      final KeyStore keyStore = KeyStore.getInstance( "JKS" ) ;
      // We don't need the storepass for just reading one password-protected certificate
      // of our own, or a trusted entry.
      keyStore.load( inputStream, null ) ;
      return keyStore ;
    }
  }


  private static final int PORT = 8443 ;

  private static final String CERTIFICATE_ALIAS = "e1";

  private static final String KEYPASS = "Keypass";

  private static final URL KEYSTORE_RESOURCE_URL
      = JettyHttpsForStackOverflow.class.getResource( "my-keystore.jks" ) ;

  private static final URL TRUSTSTORE_RESOURCE_URL
      = JettyHttpsForStackOverflow.class.getResource( "my-truststore.jks" ) ;


}

最佳答案

事实证明,Jetty-7.6.10.v20130312 中的 SslConnection 记录不正确,而加密却按预期进行。

长话短说:在创建时,SslConnectionSSLEngine 中提取初始的 SSLSession 对象,并用它继续记录。初始 SSLSession 有一个 SSL_NULL_WITH_NULL_NULL 密码,这是正常的,因为 SSL 握手尚未发生。激活-Djavax.net.debug=all显示确实发生了握手,交互式调试显示SSLEngine升级为具有真实密码的SSLSession .问题只是 Jetty 的 SslConnection 仍然使用初始 SSLSession 对象进行记录。 (它还使用来自初始 SSLSession 的值来分配缓冲区,但这是另一个问题。)

修补 SslConnection 以使用 _engine.getSession() 进行日志记录会得到预期的结果。

结语:Jetty 9 完全重写了它的 SslConnection

关于java - Jetty 日志中的 SSL_NULL_WITH_NULL_NULL 密码套件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18080996/

有关java - Jetty 日志中的 SSL_NULL_WITH_NULL_NULL 密码套件的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby-on-rails - rails : keeping DRY with ActiveRecord models that share similar complex attributes - 2

    这似乎应该有一个直截了当的答案,但在Google上花了很多时间,所以我找不到它。这可能是缺少正确关键字的情况。在我的RoR应用程序中,我有几个模型共享一种特定类型的字符串属性,该属性具有特殊验证和其他功能。我能想到的最接近的类似示例是表示URL的字符串。这会导致模型中出现大量重复(甚至单元测试中会出现更多重复),但我不确定如何让它更DRY。我能想到几个可能的方向...按照“validates_url_format_of”插件,但这只会让验证干给这个特殊的字符串它自己的模型,但这看起来很像重溶液为这个特殊的字符串创建一个ruby​​类,但是我如何得到ActiveRecord关联这个类模型

  3. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  4. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  5. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  6. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  7. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  8. ruby-on-rails - Ruby on Rails with Haml - 如何从 erb 切换 - 2

    我正在从erb文件切换到HAML。我将hamlgem添加到我的系统中。我创建了app/views/layouts/application.html.haml文件。我应该只删除application.html.erb文件吗?此外,仍然有/public/index.html文件被呈现为默认页面。我想创建自己的默认index.html.haml页面。我应该把它放在哪里以及如何使系统呈现该文件而不是默认索引文件?谢谢! 最佳答案 是的,您可以删除任何已转换为HAML的View的ERB版本。至于你的另一个问题,删除public/index/h

  9. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  10. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

随机推荐