nginx: fix HTTP/3 reuseport duplicates#5184
Conversation
|
This fix works. Thanks After this adjustment, however, the "HTTP/3 (QUIC)" option had to be set for all HTTP servers. |
|
@psychofaktory so it breaks if not all servers have the flag set? |
|
At least that was my observation. |
|
then it would make only sense as a global option and should not be configured per server or it is not configurable at all. |
|
Thank you for testing this @psychofaktory. Could you also try: curl -I --http3-only https://yourdomainI tested the scenario you described. Where HTTP3/QUIC was not enabled on all HTTP Servers and in my case it still behaved as expected. My output: curl -I --http3-only https://domain1.cz/
curl: (60) SSL: no alternative certificate subject name matches target hostname 'domain1.cz'
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the webpage mentioned above.
~ ❯ curl -I --http3-only https://domain2.cz/
HTTP/3
...
~ ❯ curl -I --http3-only https://domain3.cz
HTTP/3
...HTTP3/QUIC was enabled on domain2 and domain3. After checking the Nginx config the reuseport was set on domain2. Domain1 was configured with HTTP/2 only. |
|
I have HTTP servers for one domain and for many subdomains of this domain. If the HTTP/3 (QUIC) option is not enabled on any HTTP server, everything works perfectly. Here the result of curl -I --http3-only https://subdomain1.mydomain.com
For testing purposes, I have now disabled HTTP/3 (QUIC) for subdomain1.mydomain.com only. As a result,
I really welcome the option to enable HTTP/3 (QUIC) via the GUI. |
|
Thank you, this is very useful feedback. It is interesting that your result differs from my testing. Maybe it is interfering with something else? If you are interested we can make more tests @psychofaktory. I was also considering whether this should be implemented as a global option instead. However, in the current plugin, HTTP/2 is configured per HTTP server as well. Based on my understanding of nginx, HTTP/3/QUIC should in principle also be possible per site, so I initially followed that model. That said, it seems I am probably not able to make the per-server approach work consistently for everyone. A global option may therefore be the better choice, but that is likely a decision for the maintainers of this repository / @fabianfrz. If the maintainers decide that a global option is more appropriate, I can rework this PR in that direction with their guidance on where and how it should be exposed in the plugin. |
|
If you ask me, I would vote for the global variant if per server is not possible. However this needs a proper documentation especially in the help texts and the changelog that if this is enabled, then all ports need to also whitelisted in the firewall so it is disabled by default and the admin can update the firewall rules before there are issues with the update as some people have auto updates on. If you want to, you can also make a global variant per port (tokenize list) as this might work as well (for example support H3 on 443 but not on 8443). @fichtner, @AdSchellevis: If this gets released, it probably needs a special mention in the release notes of the update. @psychofaktory What do you think about this approch? I guess that is the most optimal solution. |
|
This proposal sounds perfect to me. Basically, I would prefer a per-server approach, as settings could be selected more granularly. As far as I understand the specification, this should also be possible. However, one must also question the extent to which it makes sense to provide HTTP2 and then, in addition, HTTP3 only for other subdomains. At least in my setup, I see no reason not to provide HTTP3 for all HTTP servers. Therefore, a global option would be perfectly sufficient. |
|
I tried to test this further, but I still cannot reproduce the behavior you are seeing (@psychofaktory). With the fixes in this PR, it behaves as expected in my testing. That said, I would not mind making this a global option instead. I am just not fully sure which direction would be preferred for the implementation, for example whether it should be done similarly to the default server handling, or exposed somewhere else. |
|
I’ve continued to test extensively over the past few days and have actually been unable to reproduce the error. I’m not sure why the behavior is different now compared to my last attempt. But as things stand, I no longer see any issues that would argue against implementing it in its current form. Apologies for the inconvenience. |
|
That is a bit strange, but I could not really understand what might have caused it to fail for you before either. In any case, no worries at all, and I really appreciate you taking the time to test it again. I still think it would be best if someone else could test it as well, just to have confirmation from a third setup and be on the safe side. |
|
Tested this in our environment with multiple vhosts and IPv6. Seems to work perfectly fine from my perspective. |
|
Thank you for taking the time to test this, @bon-sai-tree. In that case, I suppose we can move this forward and start the merge process, unless there are still any remaining concerns. @fabianfrz |
Fix HTTP/3 reuseport duplicates
This PR fixes an Nginx config-generation issue introduced while adding optional HTTP/3 (QUIC) support in nginx: add optional HTTP/3 #5071.
When multiple server blocks ended up emitting
reuseportfor the samelisten(sameaddress:port), Nginx failed to start.Reference PR: nginx: add optional HTTP/3 (#5071)
Problem
With HTTP/3 enabled on more than one server for the same
address:port, the generated configuration could containreuseportmultiple times for the same socket.reuseportis a socket option and must be applied consistently for a givenaddress:port. When duplicated across multiple server blocks for the same listener, Nginx reports an error and refuses to start.Fix
We now emit
reuseportexactly once peraddress:portfor HTTP/3:listenfor a givenaddress:portgets:quic reuseportlistendirectives for the sameaddress:portget:quic(withoutreuseport)This guarantees that the socket option is not duplicated and prevents Nginx from failing due to conflicting listen parameters.
Testing
Tested on a local OPNsense instance with multiple server blocks sharing the same
address:portand HTTP/3 enabled on more than one of them.If you have a different setup (especially more complex listener/server combinations), please give it a quick try — there may still be edge cases I did not cover.