diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c31716ac6fee..a9a762b577c1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -44,7 +44,7 @@ mockserver-client = "5.15.0" mrjar = "0.1.1" openjsse = "1.1.14" org-bouncycastle = "1.84" -org-conscrypt = "2.5.2" +org-conscrypt = "2.6-SNAPSHOT" org-junit-jupiter = "5.13.4" playservices-safetynet = "18.1.0" robolectric = "4.16.1" diff --git a/okhttp-dnsoverhttps/src/test/java/okhttp3/dnsoverhttps/EchRemoteTest.kt b/okhttp-dnsoverhttps/src/test/java/okhttp3/dnsoverhttps/EchRemoteTest.kt new file mode 100644 index 000000000000..428deb78b9f5 --- /dev/null +++ b/okhttp-dnsoverhttps/src/test/java/okhttp3/dnsoverhttps/EchRemoteTest.kt @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2026 OkHttp Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package okhttp3.dnsoverhttps + +import assertk.assertThat +import assertk.assertions.matchesPredicate +import java.net.InetAddress +import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.OkHttpClient +import okhttp3.OkHttpClientTestRule +import okhttp3.Request +import okhttp3.Response +import okhttp3.testing.PlatformRule +import org.junit.jupiter.api.Tag +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.RegisterExtension + +@Tag("Remote") +class EchRemoteTest { + @RegisterExtension + val platform = PlatformRule(requiredPlatformName = PlatformRule.CONSCRYPT_PROPERTY) + + @RegisterExtension + val clientTestRule = OkHttpClientTestRule() + + private var client = clientTestRule.newClientBuilder() + .dns( + DnsOverHttps + .Builder() + .client(clientTestRule.newClient()) + .url("https://1.1.1.1/dns-query".toHttpUrl()) + .bootstrapDnsHosts(InetAddress.getByName("1.1.1.1")) + .includeHttps(true) + .build() + ) + .build() + + @Test + fun testHttpsRequest() { + val cloudflareBody = client.sendRequest( + Request.Builder().url("https://crypto.cloudflare.com/cdn-cgi/trace").build() + ) { + it.body.string() + } + assertThat(cloudflareBody).matchesPredicate { it.contains("sni=encrypted") } + + val tlsEchBody = client.sendRequest(Request.Builder().url("https://tls-ech.dev/").build()) { + it.body.string() + } + assertThat(tlsEchBody).matchesPredicate { it.contains("You are using ECH. :)") } + } + + private fun OkHttpClient.sendRequest(request: Request, fn: (Response) -> T): T { + val response = newCall(request).execute() + + return response.use { + fn(it) + } + } +} diff --git a/okhttp/src/jvmMain/kotlin/okhttp3/internal/platform/ConscryptPlatform.kt b/okhttp/src/jvmMain/kotlin/okhttp3/internal/platform/ConscryptPlatform.kt index c309dc598000..543543ad9130 100644 --- a/okhttp/src/jvmMain/kotlin/okhttp3/internal/platform/ConscryptPlatform.kt +++ b/okhttp/src/jvmMain/kotlin/okhttp3/internal/platform/ConscryptPlatform.kt @@ -29,6 +29,7 @@ import okhttp3.Protocol import okio.ByteString import org.conscrypt.Conscrypt import org.conscrypt.ConscryptHostnameVerifier +import org.conscrypt.EchParameters /** * Platform using Conscrypt (conscrypt.org) if installed as the first Security Provider. @@ -88,6 +89,9 @@ class ConscryptPlatform private constructor() : Platform() { // Enable ALPN. val names = alpnProtocolNames(protocols) Conscrypt.setApplicationProtocols(sslSocket, names.toTypedArray()) + + // Enable ECH parameters. + Conscrypt.setEchParameters(sslSocket, EchParameters(true, echConfigList?.toByteArray())) } else { super.configureTlsExtensions(sslSocket, hostname, protocols, echConfigList) } diff --git a/settings.gradle.kts b/settings.gradle.kts index 53d4dfdba76e..203eeaaf9af2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,6 +15,7 @@ dependencyResolutionManagement { repositories { mavenCentral() google() + mavenLocal() } }