Skip to content

Add Android ECH support#9573

Draft
yschimke wants to merge 3 commits into
lysine-dev:masterfrom
yschimke:AndroidDns
Draft

Add Android ECH support#9573
yschimke wants to merge 3 commits into
lysine-dev:masterfrom
yschimke:AndroidDns

Conversation

@yschimke

Copy link
Copy Markdown
Collaborator

Initial version before dealing with NetworkSecurityPolicy,

instead just activated by developer using AndroidDns, and a server having HTTPS records with ECH.

@yschimke

Copy link
Copy Markdown
Collaborator Author

@swankjesse my biggest question is how to deal with NetworkSecurityPolicy for both
a) activation - is that AndroidDns? is that just whether to include for a specific host
b) error handling / fallback

I previously ended up with EchModes (disabled, strict and so on) read from the policy

https://github.com/lysine-dev/okhttp/pull/9383/changes#diff-62659f553c144abdf5c3d578b9d14e96bf069b4ef9e7f93549b04ff38e4fcbc9

@swankjesse swankjesse left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

THIS IS IT

private val network: Network? = null,
/**
* True to also query the `HTTPS` record for service metadata such as ECH. Set this to false to
* save a query when only IP addresses are needed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there’s a way to phrase this documentation to encourage people to keep it on.

‘Set this to false to omit the service metadata query. This will disable privacy features in the HTTPS call.’

@yschimke yschimke Jul 21, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maybe we end up defaulting to the networkSecurityConfig, but let developers opt-out, or opt-in.

For now, likely opt-in while we confirm it works.

GREASE means it should never cause failures just by being enabled.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll ask tomorrow if that mode still exists.

private val executor: Executor = Executor { it.run() },
) : Dns {
/**
* Resolves addresses only, for callers using the legacy blocking API. This delegates to

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this do a service metadata query?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, good catch.

If it's enabled, but you use lookup, we just filter it out.

Comment thread okhttp/src/androidMain/kotlin/okhttp3/android/AndroidDns.kt
Comment thread okhttp/src/androidMain/kotlin/okhttp3/android/AndroidDns.kt

/**
* Cancels a query. The system resolver doesn't call back once canceled, so this completes the
* query itself to keep the state machine from stalling.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I hope this wasn’t too painful to discover.

(I believe calling back after cancelation is the only reasonable behavior)

Comment thread okhttp/src/androidMain/kotlin/okhttp3/android/AndroidDns.kt
Comment thread okhttp/src/androidMain/kotlin/okhttp3/android/AndroidDns.kt
val echConfig =
try {
EchConfigList.fromBytes(echConfigList.toByteArray())
} catch (_: InvalidEchDataException) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ain’t great. Reducing privacy on misconfigured data is a bad look.

Just let this throw all the way to the caller instead?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this is (or was) a policy in Android.

They removed the required mode? So maybe enabled is now required?

https://cs.android.com/android/_/android/platform/frameworks/base/+/14b56d11ef2f36ad3335d757110d1020bcd6d00b

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throw for now until we have a policy

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No wait, this was the one I meant.

https://issuetracker.google.com/issues/319957694

@swankjesse

Copy link
Copy Markdown
Collaborator

I previously ended up with EchModes (disabled, strict and so on) read from the policy

My preference is we assume DNS is where this should be configured. If there’s a ECH parameter on the TYPE_HTTPS record we should use it, and if there isn’t then we should assume the site operators don‘t care.

Configuring it on the client is too difficult for large organizations, because the team that ships services and apps is far detached from the team that manages DNS and HTTPS.

@yschimke

Copy link
Copy Markdown
Collaborator Author

I previously ended up with EchModes (disabled, strict and so on) read from the policy

My preference is we assume DNS is where this should be configured. If there’s a ECH parameter on the TYPE_HTTPS record we should use it, and if there isn’t then we should assume the site operators don‘t care.

Configuring it on the client is too difficult for large organizations, because the team that ships services and apps is far detached from the team that manages DNS and HTTPS.

But there is a developer API that we should honour.

https://developer.android.com/privacy-and-security/security-config#EncryptedClientHelloSummary

yschimke added 3 commits July 21, 2026 22:38
Initial version before dealing with NetworkSecurityPolicy,
instead just activated by developer using AndroidDns, and
a server having HTTPS records with ECH.
@yschimke

Copy link
Copy Markdown
Collaborator Author

Still tests to go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants