Conversation
PostgreSQL 17+ rejects direct SSL connections without the `postgresql` ALPN protocol, so `direct_tls=True` only worked through TLS-terminating proxies. Set it on the contexts asyncpg creates, like libpq does, and document that user-provided contexts need it for direct TLS. Fixes MagicStack#1371.
DurandA
force-pushed
the
direct-tls-alpn
branch
from
September 24, 2026 09:47
abc884f to
4c06bcd
Compare
elprans
requested changes
Sep 25, 2026
elprans
left a comment
Member
There was a problem hiding this comment.
Please guard ALPN setup on builds without ALPN; default TCP connections otherwise fail.
Comment on lines
+817
to
+821
| ssl.set_alpn_protocols(_ALPN_PROTOCOLS) | ||
|
|
||
| elif ssl is True: | ||
| ssl = ssl_module.create_default_context() | ||
| ssl.set_alpn_protocols(_ALPN_PROTOCOLS) |
Member
There was a problem hiding this comment.
set_alpn_protocols() raises NotImplementedError without ALPN, breaking default ssl='prefer' connections. Guard both calls:
Suggested change
| ssl.set_alpn_protocols(_ALPN_PROTOCOLS) | |
| elif ssl is True: | |
| ssl = ssl_module.create_default_context() | |
| ssl.set_alpn_protocols(_ALPN_PROTOCOLS) | |
| if ssl_module.HAS_ALPN: | |
| ssl.set_alpn_protocols(_ALPN_PROTOCOLS) | |
| elif ssl is True: | |
| ssl = ssl_module.create_default_context() | |
| if ssl_module.HAS_ALPN: | |
| ssl.set_alpn_protocols(_ALPN_PROTOCOLS) |
Author
There was a problem hiding this comment.
Good catch, thanks. Guarded both calls in fa80694. I checked it by running the SSL tests with HAS_ALPN patched to False and set_alpn_protocols raising NotImplementedError: they pass with the guard and fail without it.
SSLContext.set_alpn_protocols() raises NotImplementedError on builds without ALPN, which broke every default (sslmode=prefer) TCP connection.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PostgreSQL 17+ rejects direct SSL connections that don't negotiate the
postgresqlALPN protocol:asyncpg never set ALPN, so
direct_tls=True(orsslnegotiation=direct) only worked through TLS-terminating proxies, not against the server itself. The existing direct TLS tests all go through the test proxy, which is why this wasn't caught.This sets ALPN on the contexts asyncpg creates (string
sslmodes andssl=True), like libpq does. It's sent for both negotiation modes, same as libpq; servers without ALPN support just ignore it.User-provided
SSLContexts are left alone, since asyncpg doesn't mutate them elsewhere either. Thedirect_tlsdocs now say to callctx.set_alpn_protocols(['postgresql'])on them.Added
test_direct_tls_native, which connects straight to the test cluster withdirect_tls=True(skipped before PG 17). Ran the SSL connection tests against PostgreSQL 18: they pass with the change, and the new test fails for every mode without it.Fixes #1371