On Fri, Apr 19, 2024 at 2:51 PM Stefan Metzmacher <metze@xxxxxxxxx> wrote: > > Hi Xin Long, > > >> But I think its unavoidable for the ALPN and SNI fields on > >> the server side. As every service tries to use udp port 443 > >> and somehow that needs to be shared if multiple services want to > >> use it. > >> > >> I guess on the acceptor side we would need to somehow detach low level > >> udp struct sock from the logical listen struct sock. > >> > >> And quic_do_listen_rcv() would need to find the correct logical listening > >> socket and call quic_request_sock_enqueue() on the logical socket > >> not the lowlevel udo socket. The same for all stuff happening after > >> quic_request_sock_enqueue() at the end of quic_do_listen_rcv. > >> > > The implementation allows one low level UDP sock to serve for multiple > > QUIC socks. > > > > Currently, if your 3 quic applications listen to the same address:port > > with SO_REUSEPORT socket option set, the incoming connection will choose > > one of your applications randomly with hash(client_addr+port) vi > > reuseport_select_sock() in quic_sock_lookup(). > > > > It should be easy to do a further match with ALPN between these 3 quic > > socks that listens to the same address:port to get the right quic sock, > > instead of that randomly choosing. > > Ah, that sounds good. > > > The problem is to parse the TLS Client_Hello message to get the ALPN in > > quic_sock_lookup(), which is not a proper thing to do in kernel, and > > might be rejected by networking maintainers, I need to check with them. > > Is the reassembling of CRYPTO frames done in the kernel or > userspace? Can you point me to the place in the code? In quic_inq_handshake_tail() in kernel, for Client Initial packet is processed when calling accept(), this is the path: quic_accept()-> quic_accept_sock_init() -> quic_packet_process() -> quic_packet_handshake_process() -> quic_frame_process() -> quic_frame_crypto_process() -> quic_inq_handshake_tail(). Note that it's with the accept sock, not the listen sock. > > If it's really impossible to do in C code maybe > registering a bpf function in order to allow a listener > to check the intial quic packet and decide if it wants to serve > that connection would be possible as last resort? That's a smart idea! man. I think the bpf hook in reuseport_select_sock() is meant to do such selection. For the Client initial packet (the only packet you need to handle), I double you will need to do the reassembling, as Client Hello TLS message is always less than 400 byte in my env. But I think you need to do the decryption for the Client initial packet before decoding it then parsing the TLS message from its crypto frame. BTW, for the TLS message parse, I have some prototype code for TLS Handshake: https://github.com/lxin/tls_hs/blob/master/crypto/tls_hs.c#L2084 The path to get ALPN: tls_msg_handle() -> tls_msg_ch_handle() -> tls_ext_handle() Hope it may be helpful to you. > > > Will you be able to work around this by using Unix Domain Sockets pass > > the sockfd to another process? > > Not really. As that would strict coordination between a lot of > independent projects. > > > (Note that we're assuming all your 3 applications are using in-kernel QUIC) > > Sure, but I guess for servers using port 443 that the only long term option. > and I don't think it will be less performant than a userspace implementation. Cool.