Akka-http: Http().webSocketClientFlow with TLS/SSL doesn't complete with failure when it should

Created on 18 Jan 2017  路  8Comments  路  Source: akka/akka-http

Hi guys,

I filed a similar issue some months ago. It was https://github.com/akka/akka/issues/21051, brilliantly resolved. Thank you for that!

This time, this issue has to do with TLS/SSL and maybe with whatever the TLSActor does together with the SSLConfig library. The following small application will make you immediately reproduce the issue:

import java.io._
import java.security._
import javax.net.ssl._

import akka.actor._
import akka.http.scaladsl._
import akka.http.scaladsl.model.ws._
import akka.stream._
import akka.stream.scaladsl._

object IssueReplicator extends App {
  implicit val system = ActorSystem()
  implicit val mat = ActorMaterializer()
  implicit val ec = system.dispatcher

  val outgoing =
    Source.single(TextMessage("hello world!"))

  val https = {
    val password = "password".toCharArray
    val keyStore = KeyStore.getInstance("JKS")
    val inputStream = new FileInputStream("any-trust-store-you-like.jks")
    try keyStore.load(inputStream, password) finally inputStream.close()
    val kmf = KeyManagerFactory.getInstance("SunX509")
    kmf.init(keyStore, password)
    val tmf = TrustManagerFactory.getInstance("SunX509")
    tmf.init(keyStore)
    val sslContext = SSLContext.getInstance("TLS")
    sslContext.init(kmf.getKeyManagers, tmf.getTrustManagers, new SecureRandom)
    ConnectionContext.https(sslContext)
  }

  val webSocketFlow = Http().webSocketClientFlow(
    WebSocketRequest("wss://unknown:8433"),
    connectionContext = https
  )

  val incoming =
    Sink.foreach[Message] {
      case message: TextMessage.Strict =>
        println(message.text)
    }

  // upgradeResponse is a Future[WebSocketUpgradeResponse]
  // and it's expected to complete with success or failure ...
  val (upgradeResponse, closed) =
  outgoing
    .viaMat(webSocketFlow)(Keep.right)
    .toMat(incoming)(Keep.both)
    .run()

  // ... BUT ... it never completes in case of failures!
  upgradeResponse.failed.foreach { ex =>
    ex.printStackTrace()
    System.exit(-1)
  }
}

Trying to connect to "wss://unknown:8443" is just an easy way to reproduce the issue. Another way is trying to connect to some TLS/SSL WebSocket servers actually up and running but making the application load an empty trust-store.jks. In the former scenario the application is expected to fail because it cannot connect to something which doesn't exist. In the latter scenario, the application is also expected to fail but for different reasons (it won't be able to validate the certificate presented by the server)

Whatever scenario you prefer to run, you'll notice that the upgradeResponse future never completes with failure when it should rather do it.

bug help wanted 1 - triaged core tls websocket

Most helpful comment

I have the same problem in akka-http 10.1.7 and akka-stream 2.5.20. It's very easy to reproduce. Use example from documentation https://doc.akka.io/docs/akka-http/current/client-side/websocket-support.html and replace address ws://echo.websocket.org with wss://unknown (it's important to use wss:// instead of ws://)

All 8 comments

I have found the same issue (I was about to open a new issue when I found this one).

I have also seen that although the upgradeResponse never completes (neither with Success nor with Failure), the closed future does complete (with Success).

Can be replicated even without the SSLContext creation just by connection to the unknown host. Here's the debug log:

[info] Running akka.http.scaladsl.WssIssueReplicator 
[info] [DEBUG] [06/12/2017 17:24:43.480] [main] [EventStream(akka://default)] logger log1-TestEventListener started
[info] [DEBUG] [06/12/2017 17:24:43.480] [main] [EventStream(akka://default)] Default Loggers started
[info] [DEBUG] [06/12/2017 17:24:43.515] [default-akka.actor.default-dispatcher-3] [akka.serialization.Serialization(akka://default)] Using serializer [akka.serialization.JavaSerializer] for message [akka.event.EventStreamUnsubscriber$Register]
[info] [DEBUG] [06/12/2017 17:24:43.584] [main] [AkkaSSLConfig(akka://default)] Initializing AkkaSSLConfig extension...
[info] [DEBUG] [06/12/2017 17:24:43.586] [main] [AkkaSSLConfig(akka://default)] buildHostnameVerifier: created hostname verifier: com.typesafe.sslconfig.ssl.DefaultHostnameVerifier@25084a1e
[info] [DEBUG] [06/12/2017 17:24:44.248] [default-akka.actor.default-dispatcher-4] [akka://default/system/IO-TCP/selectors/$a/0] Resolving unknown before connecting
[info] [DEBUG] [06/12/2017 17:24:44.257] [default-akka.actor.default-dispatcher-4] [akka.serialization.Serialization(akka://default)] Using serializer [akka.serialization.JavaSerializer] for message [akka.io.Dns$Resolve]
[info] [DEBUG] [06/12/2017 17:24:44.264] [default-akka.actor.default-dispatcher-2] [akka://default/system/IO-DNS] Resolution request for unknown from Actor[akka://default/system/IO-TCP/selectors/$a/0#970529855]
[info] [DEBUG] [06/12/2017 17:24:44.286] [default-akka.actor.default-dispatcher-9] [akka.serialization.Serialization(akka://default)] Using serializer [akka.serialization.JavaSerializer] for message [akka.io.Dns$Resolved]
[info] [DEBUG] [06/12/2017 17:24:44.300] [default-akka.actor.default-dispatcher-2] [akka://default/system/IO-TCP/selectors/$a/0] Could not establish connection to [unknown:8433] due to java.net.UnknownHostException: unknown
[info] [DEBUG] [06/12/2017 17:24:44.311] [default-akka.actor.default-dispatcher-5] [akka://default/user/StreamSupervisor-0/flow-0-1-unknown-operation] closing output

Hello akka team!
Unfortunately I also hit this problem while connecting to an unknown host which makes it hard to build a reliable application using the akka websocket client...

@jrudolph what do you think about this issue, will it be soon or later solved?
@angiolep do you still use akka as a websocket client, did you find a workaround?

Anyway, thanks for the hard work!

Dear Akka team!

Well, I seem to bump into the same problem. Cost me quite some time to debug it properly. Could this bug get some more priority? @jrudolph

Kind regards and thanks for all the hard work!

The label [help wanted] on the issue means that we do not actively work on or have resources to be able to prioritize the issue and that we want help from the community to work on it, so if you have any possibility to dig into the issue that would be great.

Thanks, I can't promise anything, but I'll look into it.

I have the same problem in akka-http 10.1.7 and akka-stream 2.5.20. It's very easy to reproduce. Use example from documentation https://doc.akka.io/docs/akka-http/current/client-side/websocket-support.html and replace address ws://echo.websocket.org with wss://unknown (it's important to use wss:// instead of ws://)

Seems to have been fixed in 10.1.12, though not sure why exactly.

Was this page helpful?
0 / 5 - 0 ratings