fix: properly handle HTTP/2 connection reuse #4902
Draft
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.
Description
When multiple domains use the same certificate (e.g. the server has a certificate that can be used for domain domain.com and subdomains a.domain.com and b.domain.com) and the server supports HTTP/2, the browser will reuse the same connection for requests to domain.com, a.domain.com, and b.domain.com.
In 1.14 this wasn't an issue because all virtual hosts lived on a single filter chain.
It's a bit different in 2.y and above. To increase host and route matching performance, virtual hosts were split across multiple filter chains, using SNI for server name matching if TLS is available. For the non-TLS case, all virtual hosts are still combined under one filter chain since hostname matching in the filter_chain_match isn't available in the cleartext case.
In more detail, let's say you have the following
Hosts andTLSContextconfiguration:This results in the following filter chain configuration:
Each
Hostis added as a virtual_host in separate filter chains.This can an issue when reusing TLS connections. A connection is established to the virtual_host that is first visited (e.g. foo.example.com) but that same connection will be reused when visiting the other virtual_host (example.com). Since the virtual_hosts live on separate filter chains, this results in a 404 because it won't be able to find foo.example.com in the route table.
The Fix
This updates so that Hosts sharing the same TLSContext will be coalesced into a single filter chain with both hosts added as server names for the filter_chain_match.
With the same
Hosts andTLSContextconfiguration above, now the generated filter chain roughly looks like:This allows for HTTP/2 connection reuse in the browser.
If a Host and TCPMapping share the same TLSContext then the existing behavior is retained, a separate filter chain is created for each. Same for the inline and implicit tls cases. i.e we do not support connection reuse with
Host.tlsor if onlyHost.tlsSecretis provided without a TLSContext.Misc
format/python,lint/pythonto run just the python linters and formatterspytest tests/unit/test_listener.py -k '<unit-test-name>[subtest-id]'.Before
After
Related Issues
fixes #2403
Testing
Added some additional unit test cases testing various scenarios to capture as many corner cases as I can and to ensure backwards compatibility with the existing behavior (hosts sharing tls context, host & tcpmapping sharing tls context, hosts/tcpmappings using different tls contexts, etc.)
Checklist
Does my change need to be backported to a previous release?
I made sure to update
CHANGELOG.md.Remember, the CHANGELOG needs to mention:
This is unlikely to impact how Ambassador performs at scale.
Remember, things that might have an impact at scale include:
My change is adequately tested.
Remember when considering testing:
I updated
DEVELOPING.mdwith any any special dev tricks I had to use to work on this code efficiently.The changes in this PR have been reviewed for security concerns and adherence to security best practices.