Hi,
I have written a small HTTPS test server and client and now I try to disable hostname verification. Here is the code:
object HttpsServer extends App {
implicit val system = ActorSystem("system")
implicit val mat = ActorMaterializer()
implicit val ec = system.dispatcher
val serverContext: HttpsContext = {
val password = "123456789".toCharArray
val context = SSLContext.getInstance("TLS")
val ks = KeyStore.getInstance("PKCS12")
val is = getClass.getResource("mykeystore.pkcs12").openStream()
ks.load(is, password)
val keyManagerFactory = KeyManagerFactory.getInstance("SunX509")
keyManagerFactory.init(ks, password)
context.init(keyManagerFactory.getKeyManagers, null, new SecureRandom)
// start up the web server
HttpsContext(context)
}
// credentials used to authenticate users
val credentials = Map("test" -> ("test", Set("user")))
// authenticator used to authenticate users, uses credentials
def authenticator[T](cred: Credentials) : Option[Set[String]] =
cred match {
case cred@Credentials.Provided(name) =>
credentials.get(name).flatMap {
case (pass, roles) =>
if(cred.verify(pass))
Some(roles)
else
None
}
case Credentials.Missing =>
None
}
val route = authenticateBasic("HTTP test server", authenticator) { roles ⇒
get {
path ("test.txt") {
complete ("Hello, World")
}
}
}
val binding = Http(system).bindAndHandle(
interface = "0.0.0.0",
port = 6443,
handler = route,
httpsContext = Some(serverContext)
)
binding onFailure {
case ex: Exception => println("Failed to bind to port 8888, reason {}", ex)
}
}
object ConnectionLevelHttpsClient extends App {
val config = ConfigFactory.parseURL(getClass.getResource("httpsclient.conf"))
implicit val system = ActorSystem("ConnectionLevelHttpsClient", config)
implicit val materializer = ActorMaterializer()
implicit val ec = system.dispatcher
val auth = Authorization(BasicHttpCredentials("test", "test"))
private val trustfulSslContext: SSLContext = {
object NoCheckX509TrustManager extends X509TrustManager {
override def checkClientTrusted(chain: Array[X509Certificate], authType: String) = ()
override def checkServerTrusted(chain: Array[X509Certificate], authType: String) = ()
override def getAcceptedIssuers = Array[X509Certificate]()
}
val context = SSLContext.getInstance("TLS")
context.init(Array[KeyManager](), Array(NoCheckX509TrustManager), null)
context
}
val trustfulClientContext: HttpsContext =
HttpsContext(trustfulSslContext)
val allHostsValid = new HostnameVerifier() {
override def verify(s: String, sslSession: SSLSession): Boolean = true
}
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid)
val connectionFlow: Flow[HttpRequest, HttpResponse, Future[Http.OutgoingConnection]] =
Http().outgoingConnectionTls("localhost", 6443, httpsContext = Some(trustfulClientContext))
val responseFuture: Future[String] =
Source.single(HttpRequest(uri = "/test.txt", headers = List(auth)))
.via(connectionFlow)
.runWith(Sink.head).flatMap { response =>
if (response.status == StatusCodes.OK) {
Unmarshal(response).to[String]
} else {
Future.successful("Error: " + response.status)
}
}
responseFuture.onSuccess {
case result => println(result)
}
responseFuture.onFailure {
case ex => ex.printStackTrace()
}
}
The whole project is here: https://github.com/mthaler/akka-http-test
The server is using a self-signed certificate and the client ignores the certificate. The code works, but when I change
Http().outgoingConnectionTls("localhost", 6443, httpsContext = Some(trustfulClientContext))
to
Http().outgoingConnectionTls("127.0.0.1", 6443, httpsContext = Some(trustfulClientContext))
I get an error:
akka.stream.ConnectionException: Hostname verification failed! Expected session to be for 127.0.0.1I tried to disable hostname verification by setting an all-trusing hostname verifier and also by including
akka.ssl-config.ssl.loose.acceptAnyCertificate=true
akka.ssl-config.loose.disableHostnameVerification = true
akka.ssl-config.ssl.loose.disableHostnameVerification = true
ssl-config.ssl.loose.acceptAnyCertificate=true
ssl-config.loose.disableHostnameVerification = true
ssl-config.ssl.loose.disableHostnameVerification = true
in httpsclient.conf. I also tried to remove my custom HttpsContext. But nothing seems to work. I am using Java 7 and akka-http 2.0.3.
How can I disable hostname verification?
(I know it is not good practice to trust all certificates and disable hostname verification.)
Best regards,
Michael