1 1.1 christos =pod 2 1.1 christos 3 1.1 christos =begin comment 4 1.1 christos 5 1.1 christos NB: Changes to the source code samples in this file should also be reflected in 6 1.1 christos demos/guide/quic-server-non-block.c 7 1.1 christos 8 1.1 christos =end comment 9 1.1 christos 10 1.1 christos =head1 NAME 11 1.1 christos 12 1.1 christos ossl-guide-quic-server-non-block 13 1.1 christos - OpenSSL Guide: Writing a simple nonblocking QUIC server 14 1.1 christos 15 1.1 christos =head1 SIMPLE NONBLOCKING QUIC SERVER EXAMPLE 16 1.1 christos 17 1.1 christos This page presents various source code samples demonstrating how to write a 18 1.1 christos simple, non-concurrent, QUIC "echo" server application which accepts one client 19 1.1 christos connection at a time, echoing input from the client back to the same client. 20 1.1 christos Once the current client disconnects, the next client connection is accepted. 21 1.1 christos 22 1.1 christos The server only accepts C<http/1.0> and C<hq-interop> ALPN's and doesn't actually 23 1.1 christos implement HTTP but only does a simple echo. This is non-standard and will not 24 1.1 christos be supported by real world servers. This is for demonstration purposes only. 25 1.1 christos 26 1.1 christos There are various methods to test this server: B<quic-client-block.c> and 27 1.1 christos B<quic-client-non-block.c> will send a basic HTTP/1.0 request, which the server 28 1.1 christos will echo back. You can also test this server by running 29 1.1 christos C<openssl s_client -connect localhost:4443 -4 -quic -alpn http/1.0> and entering 30 1.1 christos text that will be echoed back by the server. 31 1.1 christos 32 1.1 christos Both the listening socket and connected socket are "nonblocking". However, 33 1.1 christos we use select() to make the listening socket block when it cannot read/write. 34 1.1 christos Rather than stopping and waiting, your application may need to go and do other 35 1.1 christos tasks whilst the B<SSL> object is unable to read/write. For example: updating a 36 1.1 christos GUI or performing operations on some other connection or stream. 37 1.1 christos 38 1.1 christos The complete source code for this example nonblocking QUIC server is available 39 1.1 christos in the B<demos/guide> directory of the OpenSSL source distribution in the file 40 1.1 christos B<quic-server-non-block.c>. It is also available online at 41 1.1 christos L<https://github.com/openssl/openssl/blob/master/demos/guide/quic-server-non-block.c>. 42 1.1 christos 43 1.1 christos We assume that you already have OpenSSL installed on your system; that you 44 1.1 christos already have some fundamental understanding of OpenSSL concepts and QUIC (see 45 1.1 christos L<ossl-guide-libraries-introduction(7)> and L<ossl-guide-quic-introduction(7)>); 46 1.1 christos and that you know how to write and build C code and link it against the 47 1.1 christos libcrypto and libssl libraries that are provided by OpenSSL. It also assumes 48 1.1 christos that you have a basic understanding of UDP/IP and sockets. 49 1.1 christos 50 1.1 christos =head2 Creating the SSL_CTX and SSL objects 51 1.1 christos 52 1.1 christos The first step is to create an B<SSL_CTX> object for our server. We use the 53 1.1 christos L<SSL_CTX_new(3)> function for this purpose. We pass as an argument the return 54 1.1 christos value of the function L<OSSL_QUIC_server_method(3)>. You should use this method 55 1.1 christos whenever you are writing a QUIC server. 56 1.1 christos 57 1.1 christos /* 58 1.1 christos * An SSL_CTX holds shared configuration information for multiple 59 1.1 christos * subsequent per-client SSL connections. We specifically load a QUIC 60 1.1 christos * server method here. 61 1.1 christos */ 62 1.1 christos ctx = SSL_CTX_new(OSSL_QUIC_server_method()); 63 1.1 christos if (ctx == NULL) 64 1.1 christos goto err; 65 1.1 christos 66 1.1 christos Servers need a private key and certificate. Intermediate issuer CA 67 1.1 christos certificates are often required, and both the server (end-entity or EE) 68 1.1 christos certificate and the issuer ("chain") certificates are most easily configured in 69 1.1 christos a single "chain file". Below we load such a chain file (the EE certificate 70 1.1 christos must appear first), and then load the corresponding private key, checking that 71 1.1 christos it matches the server certificate. No checks are performed to check the 72 1.1 christos integrity of the chain (CA signatures or certificate expiration dates, for 73 1.1 christos example), but we do verify the consistency of the private key with the 74 1.1 christos corresponding certificate. 75 1.1 christos 76 1.1 christos /* 77 1.1 christos * Load the server's certificate *chain* file (PEM format), which includes 78 1.1 christos * not only the leaf (end-entity) server certificate, but also any 79 1.1 christos * intermediate issuer-CA certificates. The leaf certificate must be the 80 1.1 christos * first certificate in the file. 81 1.1 christos * 82 1.1 christos * In advanced use-cases this can be called multiple times, once per public 83 1.1 christos * key algorithm for which the server has a corresponding certificate. 84 1.1 christos * However, the corresponding private key (see below) must be loaded first, 85 1.1 christos * *before* moving on to the next chain file. 86 1.1 christos */ 87 1.1 christos if (SSL_CTX_use_certificate_chain_file(ctx, cert_path) <= 0) { 88 1.1 christos fprintf(stderr, "couldn't load certificate file: %s\n", cert_path); 89 1.1 christos goto err; 90 1.1 christos } 91 1.1 christos 92 1.1 christos /* 93 1.1 christos * Load the corresponding private key, this also checks that the private 94 1.1 christos * key matches the just loaded end-entity certificate. It does not check 95 1.1 christos * whether the certificate chain is valid, the certificates could be 96 1.1 christos * expired, or may otherwise fail to form a chain that a client can 97 1.1 christos * validate. 98 1.1 christos */ 99 1.1 christos if (SSL_CTX_use_PrivateKey_file(ctx, key_path, SSL_FILETYPE_PEM) <= 0) { 100 1.1 christos fprintf(stderr, "couldn't load key file: %s\n", key_path); 101 1.1 christos goto err; 102 1.1 christos } 103 1.1 christos 104 1.1 christos Most servers, including this one, do not solicit client certificates. We 105 1.1 christos therefore do not need a "trust store" and allow the handshake to complete even 106 1.1 christos when the client does not present a certificate. Note: Even if a client did 107 1.1 christos present a trusted certificate, for it to be useful, the server application 108 1.1 christos would still need custom code to use the verified identity to grant nondefault 109 1.1 christos access to that particular client. Some servers grant access to all clients 110 1.1 christos with certificates from a private CA, this then requires processing of 111 1.1 christos certificate revocation lists to deauthorise a client. It is often simpler and 112 1.1 christos more secure to instead keep a list of authorised public keys. 113 1.1 christos 114 1.1 christos Though this is the default setting, we explicitly call the 115 1.1 christos L<SSL_CTX_set_verify(3)> function and pass the B<SSL_VERIFY_NONE> value to it. 116 1.1 christos The final argument to this function is a callback that you can optionally 117 1.1 christos supply to override the default handling for certificate verification. Most 118 1.1 christos applications do not need to do this so this can safely be set to NULL to get 119 1.1 christos the default handling. 120 1.1 christos 121 1.1 christos /* 122 1.1 christos * Clients rarely employ certificate-based authentication, and so we don't 123 1.1 christos * require "mutual" TLS authentication (indeed there's no way to know 124 1.1 christos * whether or how the client authenticated the server, so the term "mutual" 125 1.1 christos * is potentially misleading). 126 1.1 christos * 127 1.1 christos * Since we're not soliciting or processing client certificates, we don't 128 1.1 christos * need to configure a trusted-certificate store, so no call to 129 1.1 christos * SSL_CTX_set_default_verify_paths() is needed. The server's own 130 1.1 christos * certificate chain is assumed valid. 131 1.1 christos */ 132 1.1 christos SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); 133 1.1 christos 134 1.1 christos 135 1.1 christos QUIC also dictates using Application-Layer Protocol Negotiation (ALPN) to select 136 1.1 christos an application protocol. We use L<SSL_CTX_set_alpn_select_cb(3)> for this 137 1.1 christos purpose. We can pass a callback which will be called for each connection to 138 1.1 christos select an ALPN the server considers acceptable. 139 1.1 christos 140 1.1 christos /* Setup ALPN negotiation callback to decide which ALPN is accepted. */ 141 1.1 christos SSL_CTX_set_alpn_select_cb(ctx, select_alpn, NULL); 142 1.1 christos 143 1.1 christos In this case, we only accept "http/1.0" and "hq-interop". 144 1.1 christos 145 1.1 christos /* 146 1.1 christos * ALPN strings for TLS handshake. Only 'http/1.0' and 'hq-interop' 147 1.1 christos * are accepted. 148 1.1 christos */ 149 1.1 christos static const unsigned char alpn_ossltest[] = { 150 1.1 christos 8, 'h', 't', 't', 'p', '/', '1', '.', '0', 151 1.1 christos 10, 'h', 'q', '-', 'i', 'n', 't', 'e', 'r', 'o', 'p', 152 1.1 christos }; 153 1.1 christos 154 1.1 christos static int select_alpn(SSL *ssl, const unsigned char **out, 155 1.1 christos unsigned char *out_len, const unsigned char *in, 156 1.1 christos unsigned int in_len, void *arg) 157 1.1 christos { 158 1.1 christos if (SSL_select_next_proto((unsigned char **)out, out_len, alpn_ossltest, 159 1.1 christos sizeof(alpn_ossltest), in, 160 1.1 christos in_len) == OPENSSL_NPN_NEGOTIATED) 161 1.1 christos return SSL_TLSEXT_ERR_OK; 162 1.1 christos return SSL_TLSEXT_ERR_ALERT_FATAL; 163 1.1 christos } 164 1.1 christos 165 1.1 christos That is all the setup that we need to do for the B<SSL_CTX>. Next, we create a 166 1.1 christos UDP socket and bind to it on localhost. 167 1.1 christos 168 1.1 christos /* Retrieve the file descriptor for a new UDP socket */ 169 1.1 christos if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 170 1.1 christos fprintf(stderr, "cannot create socket"); 171 1.1 christos return -1; 172 1.1 christos } 173 1.1 christos 174 1.1 christos sa.sin_family = AF_INET; 175 1.1 christos sa.sin_port = htons(port); 176 1.1 christos 177 1.1 christos /* Bind to the new UDP socket on localhost */ 178 1.1 christos if (bind(fd, (const struct sockaddr *)&sa, sizeof(sa)) < 0) { 179 1.1 christos fprintf(stderr, "cannot bind to %u\n", port); 180 1.1 christos BIO_closesocket(fd); 181 1.1 christos return -1; 182 1.1 christos } 183 1.1 christos 184 1.1 christos /* Set port to nonblocking mode */ 185 1.1 christos if (BIO_socket_nbio(fd, 1) <= 0) { 186 1.1 christos fprintf(stderr, "Unable to set port to nonblocking mode"); 187 1.1 christos BIO_closesocket(fd); 188 1.1 christos return -1; 189 1.1 christos } 190 1.1 christos 191 1.1 christos To run the QUIC server, we create an B<SSL_LISTENER> to listen for incoming 192 1.1 christos connections. We provide it with the bound UDP port to then explicitly begin 193 1.1 christos listening for new connections. 194 1.1 christos 195 1.1 christos /* Create a new QUIC listener */ 196 1.1 christos if ((listener = SSL_new_listener(ctx, 0)) == NULL) 197 1.1 christos goto err; 198 1.1 christos 199 1.1 christos /* Provide the listener with our UDP socket. */ 200 1.1 christos if (!SSL_set_fd(listener, fd)) 201 1.1 christos goto err; 202 1.1 christos 203 1.1 christos /* Set the listener mode to nonblocking, which is inherited by 204 1.1 christos * child objects. 205 1.1 christos */ 206 1.1 christos if (!SSL_set_blocking_mode(listener, 0)) 207 1.1 christos goto err; 208 1.1 christos 209 1.1 christos /* 210 1.1 christos * Begin listening. Note that is not usually needed as SSL_accept_connection 211 1.1 christos * will implicitly start listening. It is only needed if a server wishes to 212 1.1 christos * ensure it has started to accept incoming connections but does not wish to 213 1.1 christos * actually call SSL_accept_connection yet. 214 1.1 christos */ 215 1.1 christos if (!SSL_listen(listener)) 216 1.1 christos goto err; 217 1.1 christos 218 1.1 christos =head2 Server loop 219 1.1 christos 220 1.1 christos The server now enters a "forever" loop, handling one client connection at a 221 1.1 christos time. Before each connection, we clear the OpenSSL error stack so that any 222 1.1 christos error reports are related to just the new connection. 223 1.1 christos 224 1.1 christos /* Pristine error stack for each new connection */ 225 1.1 christos ERR_clear_error(); 226 1.1 christos 227 1.1 christos We then wait until a connection is ready for reading. 228 1.1 christos It uses the select function to wait until the socket is either readable 229 1.1 christos or writable, depending on what the SSL connection requires. 230 1.1 christos 231 1.1 christos We then accept a new connection in which the handshake will have already 232 1.1 christos occurred. However, since we are in nonblocking mode, L<SSL_accept_connection(3)> 233 1.1 christos will return immediately. Therefore, we use a helper function to essentially 234 1.1 christos block until a connection is established. 235 1.1 christos 236 1.1 christos printf("Waiting for connection\n"); 237 1.1 christos while ((conn = SSL_accept_connection(listener, 0)) == NULL) { 238 1.1 christos wait_for_activity(listener); 239 1.1 christos } 240 1.1 christos printf("Accepted new connection\n"); 241 1.1 christos 242 1.1 christos The helper function wait_for_activity uses select() to block until the file 243 1.1 christos descriptor belonging to the passed SSL object is readable. As mentioned earlier, 244 1.1 christos a more real-world application would likely use this time to perform other tasks. 245 1.1 christos 246 1.1 christos /* Initialize the fd_set structure */ 247 1.1 christos FD_ZERO(&read_fd); 248 1.1 christos FD_ZERO(&write_fd); 249 1.1 christos 250 1.1 christos /* 251 1.1 christos * Determine if we would like to write to the socket, read from it, or both. 252 1.1 christos */ 253 1.1 christos if (SSL_net_write_desired(ssl)) 254 1.1 christos FD_SET(sock, &write_fd); 255 1.1 christos if (SSL_net_read_desired(ssl)) 256 1.1 christos FD_SET(sock, &read_fd); 257 1.1 christos 258 1.1 christos /* 259 1.1 christos * Find out when OpenSSL would next like to be called, regardless of 260 1.1 christos * whether the state of the underlying socket has changed or not. 261 1.1 christos */ 262 1.1 christos if (SSL_get_event_timeout(ssl, &tv, &isinfinite) && !isinfinite) 263 1.1 christos tvp = &tv; 264 1.1 christos 265 1.1 christos /* 266 1.1 christos * Wait until the socket is writeable or readable. We use select here 267 1.1 christos * for the sake of simplicity and portability, but you could equally use 268 1.1 christos * poll/epoll or similar functions 269 1.1 christos * 270 1.1 christos * NOTE: For the purposes of this demonstration code this effectively 271 1.1 christos * makes this demo block until it has something more useful to do. In a 272 1.1 christos * real application you probably want to go and do other work here (e.g. 273 1.1 christos * update a GUI, or service other connections). 274 1.1 christos * 275 1.1 christos * Let's say for example that you want to update the progress counter on 276 1.1 christos * a GUI every 100ms. One way to do that would be to use the timeout in 277 1.1 christos * the last parameter to "select" below. If the tvp value is greater 278 1.1 christos * than 100ms then use 100ms instead. Then, when select returns, you 279 1.1 christos * check if it did so because of activity on the file descriptors or 280 1.1 christos * because of the timeout. If the 100ms GUI timeout has expired but the 281 1.1 christos * tvp timeout has not then go and update the GUI and then restart the 282 1.1 christos * "select" (with updated timeouts). 283 1.1 christos */ 284 1.1 christos 285 1.1 christos select(sock + 1, &read_fd, &write_fd, NULL, tvp); 286 1.1 christos 287 1.1 christos With the handshake complete, the server reads all the client input. 288 1.1 christos 289 1.1 christos /* Read from client until the client sends a end of stream packet */ 290 1.1 christos while (!eof) { 291 1.1 christos ret = SSL_read_ex(conn, buf + total_read, sizeof(buf) - total_read, 292 1.1 christos &nread); 293 1.1 christos total_read += nread; 294 1.1 christos if (total_read >= 8192) { 295 1.1 christos fprintf(stderr, "Could not fit all data into buffer\n"); 296 1.1 christos goto err; 297 1.1 christos } 298 1.1 christos switch (handle_io_failure(conn, ret)) { 299 1.1 christos case 1: 300 1.1 christos continue; /* Retry */ 301 1.1 christos case 0: 302 1.1 christos /* Reached end of stream */ 303 1.1 christos if (!SSL_has_pending(conn)) 304 1.1 christos eof = 1; 305 1.1 christos break; 306 1.1 christos default: 307 1.1 christos fprintf(stderr, "Failed reading remaining data\n"); 308 1.1 christos goto err; 309 1.1 christos } 310 1.1 christos } 311 1.1 christos 312 1.1 christos Finally, we echo the received data back to the client. We can use 313 1.1 christos L<SSL_write_ex2(3)> to pass in a special flag SSL_WRITE_FLAG_CONCLUDE that will 314 1.1 christos send a FIN packet once the write has successfully finished writing all the data 315 1.1 christos to the peer. 316 1.1 christos 317 1.1 christos /* Echo client input */ 318 1.1 christos while (!SSL_write_ex2(conn, buf, 319 1.1 christos total_read, 320 1.1 christos SSL_WRITE_FLAG_CONCLUDE, &total_written)) { 321 1.1 christos if (handle_io_failure(conn, 0) == 1) 322 1.1 christos continue; 323 1.1 christos fprintf(stderr, "Failed to write data\n"); 324 1.1 christos goto err; 325 1.1 christos } 326 1.1 christos 327 1.1 christos We then shut down the connection with L<SSL_shutdown(3)>, which may need 328 1.1 christos to be called multiple times to ensure the connection is shutdown completely. 329 1.1 christos 330 1.1 christos /* 331 1.1 christos * Shut down the connection. We may need to call this multiple times 332 1.1 christos * to ensure the connection is shutdown completely. 333 1.1 christos */ 334 1.1 christos while ((ret = SSL_shutdown(conn)) != 1) { 335 1.1 christos if (ret < 0 && handle_io_failure(conn, ret) == 1) 336 1.1 christos continue; /* Retry */ 337 1.1 christos } 338 1.1 christos 339 1.1 christos Finally, we free the SSL connection, and the server is now ready to accept the 340 1.1 christos next client connection. 341 1.1 christos 342 1.1 christos SSL_free(conn); 343 1.1 christos 344 1.1 christos =head2 Final clean up 345 1.1 christos 346 1.1 christos If the server somehow manages to break out of the infinite loop and 347 1.1 christos be ready to exit, it would deallocate the constructed B<SSL>. 348 1.1 christos 349 1.1 christos SSL_free(listener); 350 1.1 christos 351 1.1 christos And in the main function, it would deallocate the constructed B<SSL_CTX>. 352 1.1 christos 353 1.1 christos SSL_CTX_free(ctx); 354 1.1 christos BIO_closesocket(fd); 355 1.1 christos 356 1.1 christos =head1 SEE ALSO 357 1.1 christos 358 1.1 christos L<ossl-guide-introduction(7)>, L<ossl-guide-libraries-introduction(7)>, 359 1.1 christos L<ossl-guide-libssl-introduction(7)>, L<ossl-guide-quic-introduction(7)>, 360 1.1 christos L<ossl-guide-quic-client-non-block(7)>, L<ossl-guide-quic-client-block(7)>, 361 1.1 christos L<ossl-guide-tls-server-block(7)>, L<ossl-guide-quic-server-block(7)> 362 1.1 christos 363 1.1 christos =head1 COPYRIGHT 364 1.1 christos 365 1.1 christos Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. 366 1.1 christos 367 1.1 christos Licensed under the Apache License 2.0 (the "License"). You may not use 368 1.1 christos this file except in compliance with the License. You can obtain a copy 369 1.1 christos in the file LICENSE in the source distribution or at 370 1.1 christos L<https://www.openssl.org/source/license.html>. 371 1.1 christos 372 1.1 christos =cut 373