feat: Add "if-same-cert" sni consistency mode #216
+70
−18
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.
So yeah, I have a wildcard certificate that I use for multiple separate apps. And my browser is indeed reusing a connection to site1.example.com for service site2.example.com. I don't yet know whether it is doing it because it notices the same certificate is valid for both, or because they are served by the same IP:port combination. But I am hopeful the latter is not the case because that honestly feels a bit insane.
So yeah, by default rpxy sends 421 responses to such un-rfc behaviour. But unfortunately my browser does not either automatically re-issue the request on a different connection (MDN docs also says it is indeed optional operation). So at least one app that I have stops polling the server when this happens.
So I tested setting
ignore_sni_consistency = true
in the config. And that solved the problem. But the comments in front of the configuration option left me restless and I thought "so will it serve any configured app then, regardless of certificate?".. So I tested it and found out that yes, I could even access sites that don't have a tls certificate configured by using e.g.curl 'https://site1.example.com/' -H 'Host: site2.example.com'
where site2 does not have a tls cert configured.So I wanted a middle ground that allows this un-rfc behaviour ONLY when both the app served by the servername from sni AND the app requested by the
Host
header have the SAME certificate configured. More specifically, I defined "SAME" as "has the sametls_cert_path
".It works. I have yet to configure apps using two different certificates, will probably try that later using the built-in acme support. But even if my beloved browser decided to re-use a connection for to a site with a different certificate, I would be very angry at said browser and perhaps even file a ticket for it. So it would probably not change my stance that I want to stick to this "same-cert" middle-ground.
Anyway, this PR is my first take on adding this functionality. I initially wanted to make
ignore_sni_consistency
a three-state variable still supportingtrue
andfalse
so that existing configurations would not be broken, but alastrue
andfalse
always seem to get treated as booleans so that didn't work. Instead I added a newsamecert_sni_consistency
boolean next to it to avoid breaking existing configurations. Please give your opinion on this. How it works now is:ignore_sni_consistency
samecert_sni_consistency
Host
hostnameHost
hostnameI'll be happy to receive any feedback about this. Documentation changes not yet done. I introduced a
LazyCell<>
inhandle_request_inner()
to avoid the hashmap lookup until it is needed in one of the two places. I don't know if it makes sense performance-wise. Also if you want to support older rust versions then LazyCell is not usable. And yeah, I had to add the certificate path to the Backend object so I could compare it. But in retrospect I could also perhaps replace that with some certificate id so the comparison would be faster in the request path. Perhaps I'll do that.