Использование настраиваемого хранилища ключей с WebSocketClientFactory Jetty

У меня есть проект Java, который подключается к серверу CometD через безопасный транспорт WebSocket, который использует самозаверяющий сертификат. Я настраиваю WebSocketClientFactory следующим образом:

wssFactory.getSslContextFactory().setKeyStorePath("/path/to/my/custom.jks");
wssFactory.getSslContextFactory().setKeyStorePassword("mypass");

А затем создайте мой BayeuxClient вот так:

BayeuxClient client = new BayeuxClient(
        "wss://myserver.com/cometd",
        WebSocketTransport.create(clientOptions, wssFactory));

Действительно, когда это загружается впервые, все кажется настроенным правильно:

[DEBUG] 2012-08-07 12:58:05,786 : starting org.eclipse.jetty.websocket.WebSocketClientFactory@75cfa3d2
[DEBUG] 2012-08-07 12:58:05,786 : starting qtp2005556553{8<=0<=0/254,-1}
[DEBUG] 2012-08-07 12:58:05,788 : STARTED qtp2005556553{8<=7<=8/254,0}
[DEBUG] 2012-08-07 12:58:05,788 : starting org.eclipse.jetty.websocket.WebSocketClientFactory$WebSocketClientSelector@50c8c3b8
[DEBUG] 2012-08-07 12:58:05,795 : STARTED org.eclipse.jetty.websocket.WebSocketClientFactory$WebSocketClientSelector@50c8c3b8
[DEBUG] 2012-08-07 12:58:05,795 : Starting Thread[qtp2005556553-33 Selector0,5,main] on org.eclipse.jetty.io.nio.SelectorManager$1@346fe350
[DEBUG] 2012-08-07 12:58:05,797 : starting SslContextFactory@4240eca3(/Users/apetresc/Downloads/infrastructure.jks,null)
[INFO ] 2012-08-07 12:58:05,981 : Enabled Protocols [SSLv2Hello, SSLv3, TLSv1] of [SSLv2Hello, SSLv3, TLSv1]
[DEBUG] 2012-08-07 12:58:05,981 : Enabled Ciphers   [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_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_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV] of [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_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_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, SSL_RSA_WITH_NULL_MD5, SSL_RSA_WITH_NULL_SHA, SSL_DH_anon_WITH_RC4_128_MD5, TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_DH_anon_WITH_AES_256_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_DES_CBC_SHA, SSL_DH_anon_EXPORT_WITH_RC4_40_MD5, SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TLS_KRB5_WITH_RC4_128_SHA, TLS_KRB5_WITH_RC4_128_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_MD5, TLS_KRB5_WITH_DES_CBC_SHA, TLS_KRB5_WITH_DES_CBC_MD5, TLS_KRB5_EXPORT_WITH_RC4_40_SHA, TLS_KRB5_EXPORT_WITH_RC4_40_MD5, TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5]
[DEBUG] 2012-08-07 12:58:05,981 : STARTED SslContextFactory@4240eca3(/Users/apetresc/Downloads/infrastructure.jks,/Users/apetresc/Downloads/infrastructure.jks)
[DEBUG] 2012-08-07 12:58:05,981 : STARTED org.eclipse.jetty.websocket.WebSocketClientFactory@75cfa3d2

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

[DEBUG] 2012-08-07 13:20:37,348 : State update: CONNECTED -> CONNECTED
[DEBUG] 2012-08-07 13:20:37,348 : Connecting, transport org.cometd.websocket.client.WebSocketTransport@53ddbcb1
[DEBUG] 2012-08-07 13:20:37,348 : [Session-1, SSL_NULL_WITH_NULL_NULL] SslConnection@79c190a2 SSL NOT_HANDSHAKING i/o/u=0/0/0 ishut=false oshut=false {WebSocketClientConnection p=WebSocketParserRFC6455@5266db4e state=START buffer= g=WebSocketGeneratorRFC6455@5ec80825 closed=false buffer=-1} NOT_HANDSHAKING filled=0/0 flushed=0/0
[DEBUG] 2012-08-07 13:20:37,348 : Sending messages [{id=50, connectionType=websocket, channel=/meta/connect, clientId=2u16ol79fcq7hqe1wu52pr0ws4aw}]
[DEBUG] 2012-08-07 13:20:37,348 : Registering WebSocketExchange {id=50, connectionType=websocket, channel=/meta/connect, clientId=2u16ol79fcq7hqe1wu52pr0ws4aw}
[DEBUG] 2012-08-07 13:20:37,348 : [Session-1, SSL_NULL_WITH_NULL_NULL] SslConnection@79c190a2 SSL NOT_HANDSHAKING i/o/u=0/0/0 ishut=false oshut=false {WebSocketClientConnection p=WebSocketParserRFC6455@5266db4e state=OPCODE buffer= g=WebSocketGeneratorRFC6455@5ec80825 closed=false buffer=-1} NOT_HANDSHAKING filled=0/0 flushed=0/0
[DEBUG] 2012-08-07 13:20:37,348 : Sending messages [{"id":"50","connectionType":"websocket","channel":"/meta/connect","clientId":"2u16ol79fcq7hqe1wu52pr0ws4aw"}]
[DEBUG] 2012-08-07 13:20:37,348 : [Session-1, SSL_NULL_WITH_NULL_NULL] SslConnection@79c190a2 SSL NOT_HANDSHAKING i/o/u=0/0/0 ishut=false oshut=false {WebSocketClientConnection p=WebSocketParserRFC6455@5266db4e state=OPCODE buffer= g=WebSocketGeneratorRFC6455@5ec80825 closed=false buffer=116} NOT_HANDSHAKING filled=0/0 flushed=0/0
[DEBUG] 2012-08-07 13:20:37,349 : [Session-1, SSL_NULL_WITH_NULL_NULL] SslConnection@79c190a2 SSL NOT_HANDSHAKING i/o/u=0/0/0 ishut=false oshut=false {WebSocketClientConnection p=WebSocketParserRFC6455@5266db4e state=OPCODE buffer=null g=WebSocketGeneratorRFC6455@5ec80825 closed=false buffer=116} NOT_HANDSHAKING filled=0/0 flushed=0/0
[DEBUG] 2012-08-07 13:20:37,349 : [Session-1, SSL_NULL_WITH_NULL_NULL] wrap OK NOT_HANDSHAKING consumed=116 produced=137
[DEBUG] 2012-08-07 13:20:37,349 : [Session-1, SSL_NULL_WITH_NULL_NULL] SslConnection@79c190a2 SSL NOT_HANDSHAKING i/o/u=0/0/0 ishut=false oshut=false {WebSocketClientConnection p=WebSocketParserRFC6455@5266db4e state=OPCODE buffer=null g=WebSocketGeneratorRFC6455@5ec80825 closed=false buffer=0} NOT_HANDSHAKING filled=0/0 flushed=137/0
[DEBUG] 2012-08-07 13:20:37,349 : [Session-1, SSL_NULL_WITH_NULL_NULL] SslConnection@79c190a2 SSL NOT_HANDSHAKING i/o/u=0/0/0 ishut=false oshut=false {WebSocketClientConnection p=WebSocketParserRFC6455@5266db4e state=OPCODE buffer=null g=WebSocketGeneratorRFC6455@5ec80825 closed=false buffer=0} NOT_HANDSHAKING filled=0/0 flushed=0/0
[DEBUG] 2012-08-07 13:20:37,349 : [Session-1, SSL_NULL_WITH_NULL_NULL] handle SslConnection@79c190a2 SSL NOT_HANDSHAKING i/o/u=0/0/0 ishut=false oshut=false {WebSocketClientConnection p=WebSocketParserRFC6455@5266db4e state=OPCODE buffer=null g=WebSocketGeneratorRFC6455@5ec80825 closed=false buffer=-1} progress=false

Для меня это означает, что рукопожатие CometD завершается, а рукопожатие SSL - нет. Однако я не могу понять, почему это так; аналогичный подход работает для моих вызовов HTTPS. Только WSS вызывает у меня головную боль.

Также стоит упомянуть, что я могу воспроизвести это в различных средах, включая приложение для Android и из контейнера сервлетов Jetty.

Кто-нибудь успешно использовал WSS с самоподписанным сертификатом? Хотите пролить свет на то, что я делаю неправильно?


person Adrian Petrescu    schedule 07.08.2012    source источник
comment
Вкратце, кто-нибудь считает код ошибки SSL_NULL_WITH_NULL_NULL столь же забавно неинформативным, как я? :)   -  person Adrian Petrescu    schedule 07.08.2012
comment
SSL_NULL_WITH_NULL_NULL почти наверняка относится к набору нулевых шифров, который не обеспечивает никакой аутентификации или шифрования (и который никогда не должен быть включен ...).   -  person Bruno    schedule 07.08.2012
comment
@Bruno: Можете ли вы подробнее рассказать об этом? Судя по выходным данным журнала, мой набор шифров что угодно кроме NULL (кажется, что в нем есть десятки записей).   -  person Adrian Petrescu    schedule 07.08.2012


Ответы (2)


Во втором блоке кода вы не получаете никакой «ошибки». Это нормальный результат для ненастроенного SslContextFactory, который предоставляет набор нулевых шифров и всегда утверждающий верификатор сертификата. См. Также здесь для получения дополнительной SslContextFactory конфигурации.

Судя по журналам, в обоих случаях он работает.

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

В остальном мне кажется, что вы правильно настроили свой код.

person sbordet    schedule 07.08.2012

Я мало знаю о WebSocketClientFactory, но, насколько я понимаю, это для конфигурации на стороне клиента, когда вы, по сути, пытаетесь подключиться к серверу, настроенному с помощью самозаверяющего сертификата, копия которого хранится в вашем custom.jks файл на клиенте.

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

Попробуйте заменить setKeyStore* на setTrustStore*.

person Bruno    schedule 07.08.2012