SSL handshake didn't work same as http2 and http3

My issue:
Yield didn’t work fine on http3.

How I encountered the problem:
If I use this command : curl https://example.mncdn.org:8443 it works fine.
But if I tried curl https://example.mncdn.org:8443 --http3-only, it didn’t work fine.

Solutions I’ve tried:

My config:
daemon off;
user root;
worker_processes 1;
error_log /dev/stdout debug;
worker_rlimit_nofile 100000;
master_process off;
error_log logs/error.log debug;
worker_priority -10;

events {
multi_accept on;
use epoll;
worker_connections 51202;
}

thread_pool default threads=32 max_queue=65536;
http {
log_format quic '$remote_addr - $remote_user [$time_local] ’
'“$request” $status $body_bytes_sent ’
‘“$http_referer” “$http_user_agent” “$http3”’;

access_log logs/access.log quic;

lua_package_path "$prefixlua/?.so;;$prefixlua/module/?.so;$prefixlua/?.lua;$prefixlua/module/?.lua;;";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA;
ssl_prefer_server_ciphers on;

ssl_certificate     certs/wildcard_mncdn_org.crt;
ssl_certificate_key certs/wildcard_mncdn_org.key;

server {
    listen  8443 ssl reuseport;
    listen  8443 quic reuseport;
    server_name example.mncdn.org;

    ssl_early_data on;

    http2 on;

    ssl_certificate_by_lua_block {
        local redis = require "resty.redis"
        local red, err = redis:new()
        if not red then
            ngx.log(ngx.ERR, "failed to instantiate redis: ", err)
            return
        end
        red:set_timeouts(1000, 1000, 1000)

        local ok, err = red:connect("127.0.0.1", 6379)
        if not ok then
            ngx.log(ngx.ERR, "failed to connect redis: ", err)
            return
        end

        local value, err = red:get("foo")
        if not value then
            ngx.log(ngx.ERR, "failed to get value", err)
            return
        end

        ngx.log(ngx.DEBUG, "The value is ", value)

        print("About to initiate a new SSL handshake!")
    }
    
    location / {
        add_header Alt-Svc 'h3=":$server_port"; ma=30, h3-29=":$server_port"; ma=30';
        return 200 'Hello, world!';
    }
}

}

3 Likes

Dropping this one in the troubleshooting category.

3 Likes

I think part of the issue here is that you can only use the reuseport flag once per server block. Can you try changing listen 8443 ssl reuseport; to listen 8443 ssl; and see if that solves the problem?

2 Likes

Thank you @Damian_Curry
I did it as you told me. But it’s not working too.
Current issue occurs because of yield operation is not implemented correctly for http3.

1 Like

Would it be possible to test this without the lua code? Also, which version of NGINX are you running? I am not seeing an include statement for the lua module, I assume you are testing using a openresty build. I am curious if you see the same behavior when testing with an official NGINX build.

2 Likes

Yeah, I used openresty 1.25.3.1 version.
But I am sure that in the official nginx version, this issue will occur too.

1 Like

It might be worthwhile to test with the latest mainline version of nginx, as there have been some bug fixes related to http/3 in the newest builds.

2 Likes

Thanks for your reply.
But I think there should be a openssl patch file like openssl-1.1.1f-sess_set_get_cb_yield.patch

There is a patch file for yield, but it’s not working correctly on http3.
So I want to the community fix current bug and provide a new patch file.
Thanks

1 Like

I have finally fixed this issue.
I made a sub module where do all redis operation.
And called this API in the Lua phase.
Thus, I didn’t use default asynchronous redis operation on the Lua phase.
After that, this config works fine.

But pathing the nginx with new yield operation would be good solution.
Thank you for your considering my issue.