2017-01-10 17 views
2

У меня возникла проблема с отправкой запроса на веб-сервер под управлением IIS7 с помощью http-kit. То, что я вижу, когда я включаю режим отладки, заключается в том, что сразу после отправки запроса на получение я получаю, по-видимому, пару небольших пакетов и пучок «Игнорирование неподдерживаемого набора шифров:», за которым следует тайм-аут:SSL не работает с http-kit, но работает с простой Java

%% Cached client session: [Session-22, TLS_RSA_WITH_AES_128_CBC_SHA] 
[read] MD5 and SHA1 hashes: len = 16 
0000: 14 00 00 0C A4 24 50 40 A5 F2 3B DD 01 BB 7C A2 [email protected];..... 
Padded plaintext before ENCRYPTION: len = 208 
0000: 47 45 54 20 2F ## ## ## ## ## ## ## ## ## ## ## GET /########### 
0010: ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ################ 
0020: ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ################ 
0030: ## ## ## ## ## ## ## 20 48 54 54 50 2F 31 2E 31 ####### HTTP/1.1 
0040: 0D 0A 48 6F 73 74 3A 20 ## ## ## ## ## ## ## ## ..Host: ######## 
0050: ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ################ 
0060: ## ## ## ## ## 0D 0A 55 73 65 72 2D 41 67 65 6E #####..User-Agen 
0070: 74 3A 20 68 74 74 70 2D 6B 69 74 2F 32 2E 30 0D t: http-kit/2.0. 
0080: 0A 41 63 63 65 70 74 2D 45 6E 63 6F 64 69 6E 67 .Accept-Encoding 
0090: 3A 20 67 7A 69 70 2C 20 64 65 66 6C 61 74 65 0D : gzip, deflate. 
00A0: 0A 43 6F 6E 74 65 6E 74 2D 4C 65 6E 67 74 68 3A .Content-Length: 
00B0: 20 30 0D 0A 0D 0A AF DD 9B 8A C3 9A BB BE 20 8B 0............ . 
00C0: 94 AB 63 0F 74 80 4D 59 F4 73 05 05 05 05 05 05 ..c.t.MY.s...... 
client-loop, WRITE: TLSv1 Application Data, length = 182 
[Raw write (bb)]: length = 213 
0000: 17 03 01 00 D0 92 D5 AB 1C 3E 93 5F 45 C1 30 0D .........>._E.0. 
0010: 25 6A 5F E7 67 06 2B 2B 2A B4 1E E5 7E EE 6C 96 %j_.g.++*.....l. 
0020: F5 A6 D0 19 37 3E 30 9D 99 6B 8F 75 E3 35 16 02 ....7>0..k.u.5.. 
0030: 90 4E 6D 22 A5 FE FF 37 E9 DF 7C 38 25 4B 05 6D .Nm"...7...8%K.m 
0040: CC 0A 8E 0E 3A 43 44 1F 23 83 D6 C4 4E B5 55 45 ....:CD.#...N.UE 
0050: 58 7B 53 6E 03 2B 73 08 E6 EB 1E 49 75 B9 6E B4 X.Sn.+s....Iu.n. 
0060: 2F 7D 6F 9A B2 B9 15 90 5F C7 82 67 98 39 AE 07 /.o....._..g.9.. 
0070: DC D0 53 B7 6C C2 C3 BE 7F 40 3F 73 DF 56 8A 3B [email protected]?s.V.; 
0080: D2 A2 EF F7 16 AC 4E F9 4C 75 F8 B1 A6 3B 95 F6 ......N.Lu...;.. 
0090: 92 73 AF 84 C0 52 6A 08 77 8C A7 B1 18 A4 71 B7 .s...Rj.w.....q. 
00A0: B6 8C 56 19 7A A1 12 6C E6 94 B0 84 C1 40 89 6D [email protected] 
00B0: B7 D5 8C F5 57 80 3E 19 2D 11 24 B3 88 A2 F5 9C ....W.>.-.$..... 
00C0: FA 38 F9 D7 E8 1F 7B 7E 9F 72 68 BF 8C 82 D6 1E .8.......rh..... 
00D0: B7 3D 33 06 98          .=3.. 
[Raw read]: length = 5 
0000: 16 03 01 00 20          .... 
[Raw read]: length = 32 
0000: AA AA D1 B2 BE D1 00 84 C1 93 BF 8A 9A 77 ED 76 .............w.v 
0010: 53 BB E0 3B 4B DB E6 A6 92 00 D0 2E 05 B7 4F EF S..;K.........O. 
client-loop, READ: TLSv1 Handshake, length = 32 
Padded plaintext after DECRYPTION: len = 32 
0000: 00 00 00 00 C5 5C 82 7D 4D E6 C8 3D F5 2D F6 9F .....\..M..=.-.. 
0010: 64 B6 F9 DF 53 90 99 3F 07 07 07 07 07 07 07 07 d...S..?........ 
Allow unsafe renegotiation: false 
Allow legacy hello messages: true 
Is initial handshake: false 
Is secure renegotiation: true 
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1 
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1 
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1 
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1 
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1 
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1 
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1 
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_GCM_SHA384 
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_GCM_SHA256 
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 
=> 
{:opts {:sslengine #object[sun.security.ssl.SSLEngineImpl 
          0x7a21e0f7 
          "7a21e0f7[SSLEngine[hostname=null port=-1] TLS_RSA_WITH_AES_128_CBC_SHA]"], 
     :timeout 4000, 
     :method :get, 
     :url "https://################################################################################"}, 
:error #error{:cause "read timeout: 4000ms", 
       :via [{:type org.httpkit.client.TimeoutException, 
         :message "read timeout: 4000ms", 
         :at [org.httpkit.client.HttpClient clearTimeout "HttpClient.java" 82]}], 
       :trace [[org.httpkit.client.HttpClient clearTimeout "HttpClient.java" 82] 
         [org.httpkit.client.HttpClient run "HttpClient.java" 433] 
         [java.lang.Thread run "Thread.java" 745]]}} 

код, который делает это случается выглядит следующим образом:

@(org.httpkit.client/get "https://################################################################################" 
         {:sslengine (build-ssl-engine (build-ssl-context {:keystore "####################" :keystore-pass "########" 
                      :trust-store "####################" :trust-store-pass "########" 
                      :protocol "TLSv1"})) 
          :timeout 4000}) 

вспомогательные функции:

(defn- setup-keystore ^KeyStore [file ^String password] 
    (let [keystore (KeyStore/getInstance "JKS")] 
    (with-open [inputstream (io/input-stream (io/resource file))] 
     (.load keystore inputstream (.toCharArray password))) 
    keystore)) 

(defn- key-managers [file ^String password] 
    (let [manager-factory (KeyManagerFactory/getInstance (KeyManagerFactory/getDefaultAlgorithm))] 
    (.init manager-factory (setup-keystore file password) (.toCharArray password)) 
    (.getKeyManagers manager-factory))) 

(defn- trust-managers [file password] 
    (let [manager-factory (TrustManagerFactory/getInstance (TrustManagerFactory/getDefaultAlgorithm))] 
    (.init manager-factory (setup-keystore file password)) 
    (.getTrustManagers manager-factory))) 

(defn build-ssl-context ^javax.net.ssl.SSLContext [{:keys [trust-store trust-store-pass keystore keystore-pass protocol] 
                :or {protocol "TLS"}}] 
    (let [key-managers (key-managers keystore keystore-pass) 
     trust-managers (trust-managers trust-store trust-store-pass) 
     ssl-context (SSLContext/getInstance protocol)] 
    (.init ssl-context key-managers trust-managers nil) 
    (SSLContext/setDefault ssl-context) 
    ssl-context)) 

(defn build-ssl-engine [^SSLContext ssl-context] 
    (doto (.createSSLEngine ssl-context) 
    (.setUseClientMode true) 
    (.setNeedClientAuth true))) 

Теперь у меня есть кусок кода Java, который похож, но работает.

%% Cached client session: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA] 
[read] MD5 and SHA1 hashes: len = 16 
0000: 14 00 00 0C D2 53 C9 75 95 CC 0C E5 48 44 0E 7C .....S.u....HD.. 
Padded plaintext before ENCRYPTION: len = 240 
0000: 47 45 54 20 ## ## ## ## ## ## ## ## ## ## ## ## GET /########### 
0010: ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ################ 
0020: ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ################ 
0030: ## ## ## ## ## ## ## 20 48 54 54 50 2F 31 2E 31 ####### HTTP/1.1 
0040: 0D 0A 55 73 65 72 2D 41 67 65 6E 74 3A 20 4A 61 ..User-Agent: Ja 
0050: 76 61 2F 31 2E 38 2E 30 5F 31 31 32 0D 0A 48 6F va/1.8.0_112..Ho 
0060: 73 74 3A 20 ## ## ## ## ## ## ## ## ## ## ## ## st: ############ 
0070: ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ################ 
0080: ## 0D 0A 41 63 63 65 70 74 3A 20 74 65 78 74 2F #..Accept: text/ 
0090: 68 74 6D 6C 2C 20 69 6D 61 67 65 2F 67 69 66 2C html, image/gif, 
00A0: 20 69 6D 61 67 65 2F 6A 70 65 67 2C 20 2A 3B 20 image/jpeg, *; 
00B0: 71 3D 2E 32 2C 20 2A 2F 2A 3B 20 71 3D 2E 32 0D q=.2, */*; q=.2. 
00C0: 0A 43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 6B 65 65 .Connection: kee 
00D0: 70 2D 61 6C 69 76 65 0D 0A 0D 0A 82 2E C5 FA E3 p-alive......... 
00E0: B7 BC 64 D0 AE 36 F6 FE 0A E7 38 D3 0A 39 76 00 ..d..6....8..9v. 
main, WRITE: TLSv1 Application Data, length = 240 
[Raw write]: length = 245 
0000: 17 03 01 00 F0 34 28 EC E7 31 92 96 43 E2 36 83 .....4(..1..C.6. 
0010: AA 59 C1 CD EC 08 0D 8F 02 F0 3B 9D 3C 0A 65 73 .Y........;.<.es 
0020: E7 FF 7E 08 5A 39 F2 16 AB 7F 02 CF B3 E4 A3 14 ....Z9.......... 
0030: 46 A4 EC 5A 1C B2 81 7B CA 65 78 5E DF 19 48 40 F..Z.....ex^[email protected] 
0040: 2F 2B 0F D4 BB 6D 09 52 C6 14 BC C8 D2 C5 41 8A /+...m.R......A. 
0050: 91 5F 90 53 A9 E3 15 21 2E 7C 8E 7B 2B E5 46 D6 ._.S...!....+.F. 
0060: 9A 32 8F DF 35 49 6C 9A DA CB 02 BA BE 83 1D D3 .2..5Il......... 
0070: 39 D6 C5 F4 E9 27 E9 1D A6 3F 0E BB C8 BE A0 6C 9....'...?.....l 
0080: 32 97 BC FC 0C 04 68 8F CC 6B DA AF F2 40 2D 56 [email protected] 
0090: 47 EC 92 F5 36 19 FF F6 B4 97 31 9F 5D F0 75 31 G...6.....1.].u1 
00A0: 12 6A AD D2 FA 95 22 A5 F7 D8 20 36 D9 F9 69 87 .j...."... 6..i. 
00B0: 67 05 AE 97 68 81 8D C4 38 AC 74 6A B7 DB 51 DE g...h...8.tj..Q. 
00C0: A2 65 86 F1 F4 F7 27 2C 3D 3C 85 BE DB 97 01 C7 .e....',=<...... 
00D0: 70 CE 19 FE D6 44 24 AE F3 38 79 C2 B9 DE 71 EB p....D$..8y...q. 
00E0: 47 1A 3A 94 E8 3D F9 A0 DD 51 FD CE 01 84 E7 23 G.:..=...Q.....# 
00F0: 8B F8 07 B2 2D          ....- 
[Raw read]: length = 5 
0000: 16 03 01 00 20          .... 
[Raw read]: length = 32 
0000: E6 11 77 2F 9D 87 61 F5 FE 99 0D 62 51 7E D0 93 ..w/..a....bQ... 
0010: 55 D2 4B B3 E8 91 DC F6 69 D8 2E 2E BF F4 B2 0F U.K.....i....... 
main, READ: TLSv1 Handshake, length = 32 
Padded plaintext after DECRYPTION: len = 32 
0000: 00 00 00 00 43 53 ED 57 2D 63 29 89 E3 20 9C DD ....CS.W-c).. .. 
0010: 17 58 AA E5 3D 13 BC BB 07 07 07 07 07 07 07 07 .X..=........... 
Allow unsafe renegotiation: false 
Allow legacy hello messages: true 
Is initial handshake: false 
Is secure renegotiation: true 
*** HelloRequest (empty) 
%% Client cached [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA] 
%% Try resuming [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA] from port 57365 
*** ClientHello, TLSv1 

Почти equilavent код Java является:

public class Main { 
    public static void main(String[] args) { 
     try { 
      String keystore = "####################"; 
      String keystorePassword = "########"; 
      String trustStore = "####################"; 
      String trustStorePassword = "########"; 
      String protocol = "TLSv1"; 

      buildSslContext(keystore, keystorePassword, trustStore, trustStorePassword, protocol); 

      URL url = new URL("https://################################################################################"); 
      HttpsURLConnection httpsCon = (HttpsURLConnection) url.openConnection(); 
      httpsCon.setRequestMethod("GET"); 
      String responseMessage = httpsCon.getResponseMessage(); 

      System.out.printf("Response Message is %s\n", responseMessage); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private static void buildSslContext(String keystore, String keystorePassword, String trustStore, String trustStorePassword, String protocol) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException { 
     SSLContext sslContext = SSLContext.getInstance(protocol); 
     KeyManager[] keyManagers = keyManagers(keystore, keystorePassword); 
     TrustManager[] trustManagers = trustManagers(trustStore, trustStorePassword); 
     sslContext.init(keyManagers, trustManagers, null); 
     SSLContext.setDefault(sslContext); 
    } 

    private static TrustManager[] trustManagers(String file, String password) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { 
     KeyStore trustStore = setupKeystore(file, password); 
     TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
     trustManagerFactory.init(trustStore); 
     return trustManagerFactory.getTrustManagers(); 
    } 

    private static KeyManager[] keyManagers(String file, String password) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException { 
     KeyStore keyStore = setupKeystore(file, password); 
     KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
     keyManagerFactory.init(keyStore, password.toCharArray()); 
     return keyManagerFactory.getKeyManagers(); 
    } 

    private static KeyStore setupKeystore(String file, String password) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { 
     InputStream trustStoreUrl = new FileInputStream(file); 
     KeyStore trustStore = KeyStore.getInstance("JKS"); 
     trustStore.load(trustStoreUrl, password.toCharArray()); 
     return trustStore; 
    } 
} 

Большая разница в том, что код Clojure создает свой собственный SSLEngine в то время как Java-код, кажется, работает только, сделав SSLContext по умолчанию один. Кажется, Java создает SSLEngine из этого контекста, в то время как http-kit ожидает, что вы его предоставите. Обратите внимание, что я исправляю его до TLSv1, потому что этот IIS 7 убивает соединение, если я использую TLSv1.1 или v1.2.

Любые идеи, что происходит и как их исправить?

ответ

1

Я предоставлю это «Я не человек Clojure», но я думаю, вы правы, что вам нужно предоставить свой собственный SSLContext в код http-kit. Существует хороший blog post here, в котором обсуждается, как использовать библиотеку Clojure под названием less-awful-ssl, чтобы сгенерировать SSLContext и предоставить ее в качестве карты opts в метод запроса http-kit через (.createSSLEngine ctx), который даст вам правильный SSLEngine.

Для записи я часто видел (даже в чистой Java) сообщение «Игнорирование неподдерживаемого шифрованного набора» для всех номинально поддерживаемых наборов, когда предоставленное хранилище ключей не имеет ключа RSA/DSA или сертификата (т.е. даты истекли и т. д.).

+0

Контекст, который я генерирую, хорош, насколько вам известно, и использование менее ужасного ssl потребует довольно много манипулирования ключами, но я попробовал менее ужасный ssl-context-> ssl-engine ssl ssl, и я все равно получаю то же самое проблема. – Pablo