Skip to content

SSL(TLS)

HOA PHAN edited this page Jun 27, 2022 · 15 revisions

SYS

openssl s_client -connect  google.com:443

COST of TLS handshake

curl -w "dns_resolution: %{time_namelookup}, tcp_established: %{time_connect}, ssl_handshake_done: %{time_appconnect}, TTFB: %{time_starttransfer}\n" -o /dev/null -s "https://sushi.herokuapp.com/"

JAVA

bash-4.3# cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.4.6
PRETTY_NAME="Alpine Linux v3.4"
HOME_URL="http://alpinelinux.org"
BUG_REPORT_URL="http://bugs.alpinelinux.org"

keytool -list -v -keystore /opt/jdk/jre/lib/security/cacerts

#https://docs.oracle.com/javase/8/docs/api/java/net/doc-files/net-properties.html

REACTIVE netty

package com.example.reactivewebclient

//https://github.com/reactor/reactor-netty/pull/1455
import io.netty.channel.ChannelOption.CONNECT_TIMEOUT_MILLIS
import io.netty.handler.timeout.ReadTimeoutHandler
import io.netty.handler.timeout.WriteTimeoutHandler
import mu.KotlinLogging
import org.springframework.http.HttpMethod.GET
import org.springframework.http.MediaType
import org.springframework.http.client.reactive.ReactorClientHttpConnector
import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.BodyInserters
import org.springframework.web.reactive.function.client.WebClient
import reactor.core.publisher.Mono
import reactor.netty.http.client.HttpClient
import java.time.Duration.ofMillis
import java.util.concurrent.TimeUnit


@Service
class BSService(webclientB: WebClient.Builder) {
    private val log = KotlinLogging.logger {}

    lateinit var webClient: WebClient

    init {
        val httpClient: HttpClient = HttpClient.create()
            .option(CONNECT_TIMEOUT_MILLIS, 5000)
            .responseTimeout(ofMillis(5000))
            .doOnConnected { conn ->
                conn.addHandlerLast(ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS))
                    .addHandlerLast(WriteTimeoutHandler(5000, TimeUnit.MILLISECONDS))
            }
        //warm the fuck up
        httpClient.warmup().subscribe()

        webClient = webclientB
            .clientConnector(ReactorClientHttpConnector(httpClient))
            .baseUrl("https://data.nsw.gov.au/data/api/3/action/datastore_search")
            .build()
        log.info { "webclient BUILT" }
    }

    fun get(): Mono<String> {
        return webClient.method(GET)
            .contentType(MediaType.APPLICATION_JSON)
            .body(BodyInserters.fromValue("{\"resource_id\": \"2776dbb8-f807-4fb2-b1ed-184a6fc2c8aa\", \"limit\": 5, \"q\": \"jones\" }"))
            .retrieve()
            .bodyToMono(String::class.java)
            .onErrorResume { handleErr(it) }
    }

    private fun handleErr(t:Throwable):Mono<String> {
        log.error("MOTHERFUCVKER", t)
        return Mono.just("BLEEP")
    }
}

https://github.com/benjaminknauer/spring-mvc-web-client-first-request-slow-demo

TLS 1.3

Perf

https://www.oracle.com/java/technologies/javase/8u261-relnotes.html

https://bugs.openjdk.java.net/browse/JDK-8248721

https://github.com/netty/netty/commit/b1d3aad404a39143da7a86c121d60f35c0d21108

Sample: openssl s_client -connect data.nsw.gov.au:443 -prexit #TLSv1.2 openssl s_client -connect okta.com:443 -prexit #TLSv1.2 openssl s_client -connect aalto.fi:443 -prexit #TLSv1.3

curl -w "dns_resolution: %{time_namelookup}, tcp_established: %{time_connect}, ssl_handshake_done: %{time_appconnect}, TTFB: %{time_starttransfer}\n" -o /dev/null -s "https://iag-nrma-silver-prd.okta.com/"

MTLS client

supposed

curl -vvv --cacert /Users/hoaphan/dev/code/springboot-tls/client.pem \
    --key /Users/hoaphan/openssl/client-key1.pem \
    --cert /Users/hoaphan/openssl/client-cert1.pem \
    https://localhost:8080/actuator

now this in Kotlin:

kotlin

    fun testMTLS() {
        val sslContext: SslContext = sslContext()!!

        val httpClient: HttpClient = HttpClient.create().secure {
                sslSpec -> sslSpec.sslContext(sslContext)
        }

        val client = WebClient.builder()
            .clientConnector(ReactorClientHttpConnector(httpClient))
            .baseUrl("https://localhost:8080/actuator")
            .build()
        val res = client.get()
            .retrieve()
            .bodyToMono(String::class.java)
        StepVerifier
            .create(res)
            .expectNext("""{"_links":{"self":{"href":"https://localhost:8080/actuator","templated":false},"health":{"href":"https://localhost:8080/actuator/health","templated":false},"health-path":{"href":"https://localhost:8080/actuator/health/{*path}","templated":true}}}""")
            .expectComplete()
            .verify()
    }

    private fun sslContext(): SslContext{
        val clientSslKeyStorePassword = "changeit"
        val clientSslTrustStorePassword:String = "changeit"

        FileInputStream("/Users/hoaphan/dev/code/springboot-tls/client/cert.jks").use { keyStoreFileInputStream ->

            FileInputStream("/Users/hoaphan/.sdkman/candidates/java/11.0.11.hs-adpt/lib/security/cacerts").use { trustStoreFileInputStream ->
                val keyStore = KeyStore.getInstance("jks")
                keyStore.load(keyStoreFileInputStream, clientSslKeyStorePassword.toCharArray())
                val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance("SunX509")
                keyManagerFactory.init(keyStore, clientSslKeyStorePassword.toCharArray())

                val trustStore = KeyStore.getInstance("jks")
                trustStore.load(trustStoreFileInputStream, clientSslTrustStorePassword.toCharArray())
                val trustManagerFactory: TrustManagerFactory = TrustManagerFactory.getInstance("SunX509")
                trustManagerFactory.init(trustStore)

                return SslContextBuilder
                    .forClient()
                    .keyManager(keyManagerFactory)
                    .trustManager(trustManagerFactory)
                    .build()
            }
        }
    }

eye

Clone this wiki locally