Remove NPN

This commit is contained in:
Tatsuhiro Tsujikawa
2023-12-23 19:20:02 +09:00
parent 69e15e8371
commit 6c01530ff3
23 changed files with 73 additions and 423 deletions

View File

@@ -29,10 +29,10 @@ Public Test Server
The following endpoints are available to try out our nghttp2
implementation.
* https://nghttp2.org/ (TLS + ALPN/NPN and HTTP/3)
* https://nghttp2.org/ (TLS + ALPN and HTTP/3)
This endpoint supports ``h2``, ``h2-16``, ``h2-14``, and
``http/1.1`` via ALPN/NPN and requires TLSv1.2 for HTTP/2
``http/1.1`` via ALPN and requires TLSv1.2 for HTTP/2
connection.
It also supports HTTP/3.
@@ -537,7 +537,7 @@ nghttp - client
+++++++++++++++
``nghttp`` is a HTTP/2 client. It can connect to the HTTP/2 server
with prior knowledge, HTTP Upgrade and NPN/ALPN TLS extension.
with prior knowledge, HTTP Upgrade and ALPN TLS extension.
It has verbose output mode for framing information. Here is sample
output from ``nghttp`` client:
@@ -763,8 +763,8 @@ nghttpd - server
By default, it uses SSL/TLS connection. Use ``--no-tls`` option to
disable it.
``nghttpd`` only accepts HTTP/2 connections via NPN/ALPN or direct
HTTP/2 connections. No HTTP Upgrade is supported.
``nghttpd`` only accepts HTTP/2 connections via ALPN or direct HTTP/2
connections. No HTTP Upgrade is supported.
The ``-p`` option allows users to configure server push.
@@ -845,7 +845,7 @@ to know how to migrate from earlier releases.
``nghttpx`` implements `important performance-oriented features
<https://istlsfastyet.com/#server-performance>`_ in TLS, such as
session IDs, session tickets (with automatic key rotation), OCSP
stapling, dynamic record sizing, ALPN/NPN, forward secrecy and HTTP/2.
stapling, dynamic record sizing, ALPN, forward secrecy and HTTP/2.
``nghttpx`` also offers the functionality to share session cache and
ticket keys among multiple ``nghttpx`` instances via memcached.

View File

@@ -30,8 +30,8 @@ In order to set benchmark settings, specify following 3 options.
:option:`-m`
The max concurrent streams to issue per client. Default: 1
For SSL/TLS connection, the protocol will be negotiated via ALPN/NPN.
You can set specific protocols in :option:`--npn-list` option. For
For SSL/TLS connection, the protocol will be negotiated via ALPN. You
can set specific protocols in :option:`--npn-list` option. For
cleartext connection, the default protocol is HTTP/2. To change the
protocol in cleartext connection, use :option:`--no-tls-proto` option.
For convenience, :option:`--h1` option forces HTTP/1.1 for both

View File

@@ -20,7 +20,7 @@ known as "HTTP/2 router".
By default, frontend connection is encrypted using SSL/TLS. So
server's private key and certificate must be supplied to the command
line (or through configuration file). In this case, the frontend
protocol selection will be done via ALPN or NPN.
protocol selection will be done via ALPN.
To turn off encryption on frontend connection, use ``no-tls`` keyword
in :option:`--frontend` option. HTTP/2 and HTTP/1 are available on

View File

@@ -18,34 +18,8 @@ note that nghttp2 itself does not depend on libevent.
The client starts with some libevent and OpenSSL setup in the
``main()`` and ``run()`` functions. This setup isn't specific to
nghttp2, but one thing you should look at is setup of the NPN
callback. The NPN callback is used by the client to select the next
application protocol over TLS. In this tutorial, we use the
`nghttp2_select_next_protocol()` helper function to select the HTTP/2
protocol the library supports::
static int select_next_proto_cb(SSL *ssl _U_, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg _U_) {
if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
errx(1, "Server did not advertise " NGHTTP2_PROTO_VERSION_ID);
}
return SSL_TLSEXT_ERR_OK;
}
If you are following TLS related RFC, you know that NPN is not the
standardized way to negotiate HTTP/2. NPN itself is not event
published as RFC. The standard way to negotiate HTTP/2 is ALPN,
Application-Layer Protocol Negotiation Extension, defined in `RFC 7301
<https://tools.ietf.org/html/rfc7301>`_. The one caveat of ALPN is
that OpenSSL >= 1.0.2 is required. We use macro to enable/disable
ALPN support depending on OpenSSL version. OpenSSL's ALPN
implementation does not require callback function like the above. But
we have to instruct OpenSSL SSL_CTX to use ALPN, which we'll talk
about soon.
The callback is added to the SSL_CTX object using
``SSL_CTX_set_next_proto_select_cb()``::
nghttp2, but one thing you should look at is setup of ALPN. Client
tells application protocols that it supports to server via ALPN::
static SSL_CTX *create_ssl_ctx(void) {
SSL_CTX *ssl_ctx;
@@ -58,7 +32,6 @@ The callback is added to the SSL_CTX object using
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
@@ -153,10 +126,7 @@ underlying network socket::
ssl = bufferevent_openssl_get_ssl(session_data->bev);
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
if (alpn == NULL) {
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
}
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
fprintf(stderr, "h2 is not negotiated\n");

View File

@@ -21,33 +21,11 @@ note that nghttp2 itself does not depend on libevent.
The server starts with some libevent and OpenSSL setup in the
``main()`` and ``run()`` functions. This setup isn't specific to
nghttp2, but one thing you should look at is setup of the NPN
callback. The NPN callback is used by the server to advertise which
application protocols the server supports to a client. In this
example program, when creating the ``SSL_CTX`` object, we store the
application protocol name in the wire format of NPN in a statically
allocated buffer. This is safe because we only create one ``SSL_CTX``
object in the program's entire lifetime.
If you are following TLS related RFC, you know that NPN is not the
standardized way to negotiate HTTP/2. NPN itself is not even
published as RFC. The standard way to negotiate HTTP/2 is ALPN,
Application-Layer Protocol Negotiation Extension, defined in `RFC 7301
<https://tools.ietf.org/html/rfc7301>`_. The one caveat of ALPN is
that OpenSSL >= 1.0.2 is required. We use macro to enable/disable
ALPN support depending on OpenSSL version. In ALPN, client sends the
list of supported application protocols, and server selects one of
them. We provide the callback for it::
static unsigned char next_proto_list[256];
static size_t next_proto_list_len;
static int next_proto_cb(SSL *s _U_, const unsigned char **data,
unsigned int *len, void *arg _U_) {
*data = next_proto_list;
*len = (unsigned int)next_proto_list_len;
return SSL_TLSEXT_ERR_OK;
}
nghttp2, but one thing you should look at is setup of ALPN callback.
The ALPN callback is used by the server to select application
protocols offered by client. In ALPN, client sends the list of
supported application protocols, and server selects one of them. We
provide the callback for it::
static int alpn_select_proto_cb(SSL *ssl _U_, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
@@ -71,28 +49,11 @@ them. We provide the callback for it::
...
next_proto_list[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
memcpy(&next_proto_list[1], NGHTTP2_PROTO_VERSION_ID,
NGHTTP2_PROTO_VERSION_ID_LEN);
next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
return ssl_ctx;
}
The wire format of NPN is a sequence of length prefixed strings, with
exactly one byte used to specify the length of each protocol
identifier. In this tutorial, we advertise the specific HTTP/2
protocol version the current nghttp2 library supports, which is
exported in the identifier :macro:`NGHTTP2_PROTO_VERSION_ID`. The
``next_proto_cb()`` function is the server-side NPN callback. In the
OpenSSL implementation, we just assign the pointer to the NPN buffers
we filled in earlier. The NPN callback function is set to the
``SSL_CTX`` object using ``SSL_CTX_set_next_protos_advertised_cb()``.
In ``alpn_select_proto_cb()``, we use `nghttp2_select_next_protocol()`
to select application protocol. The `nghttp2_select_next_protocol()`
returns 1 only if it selected h2 (ALPN identifier for HTTP/2), and out
@@ -209,10 +170,7 @@ underlying network socket::
ssl = bufferevent_openssl_get_ssl(session_data->bev);
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
if (alpn == NULL) {
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
}
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);

View File

@@ -345,29 +345,6 @@ static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
callbacks, on_data_chunk_recv_callback);
}
#ifndef OPENSSL_NO_NEXTPROTONEG
/*
* Callback function for TLS NPN. Since this program only supports
* HTTP/2 protocol, if server does not offer HTTP/2 the nghttp2
* library supports, we terminate program.
*/
static int select_next_proto_cb(SSL *ssl, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg) {
int rv;
(void)ssl;
(void)arg;
/* nghttp2_select_next_protocol() selects HTTP/2 protocol the
nghttp2 library supports. */
rv = nghttp2_select_next_protocol(out, outlen, in, inlen);
if (rv <= 0) {
die("Server did not advertise HTTP/2 protocol");
}
return SSL_TLSEXT_ERR_OK;
}
#endif /* !OPENSSL_NO_NEXTPROTONEG */
/*
* Setup SSL/TLS context.
*/
@@ -376,10 +353,6 @@ static void init_ssl_ctx(SSL_CTX *ssl_ctx) {
SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
/* Set NPN callback */
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
#endif /* !OPENSSL_NO_NEXTPROTONEG */
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
}

View File

@@ -308,23 +308,6 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
return 0;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
/* NPN TLS extension client callback. We check that server advertised
the HTTP/2 protocol the nghttp2 library supports. If not, exit
the program. */
static int select_next_proto_cb(SSL *ssl, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg) {
(void)ssl;
(void)arg;
if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
errx(1, "Server did not advertise " NGHTTP2_PROTO_VERSION_ID);
}
return SSL_TLSEXT_ERR_OK;
}
#endif /* !OPENSSL_NO_NEXTPROTONEG */
/* Create SSL_CTX. */
static SSL_CTX *create_ssl_ctx(void) {
SSL_CTX *ssl_ctx;
@@ -337,9 +320,6 @@ static SSL_CTX *create_ssl_ctx(void) {
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
#endif /* !OPENSSL_NO_NEXTPROTONEG */
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
@@ -506,9 +486,6 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) {
ssl = bufferevent_openssl_get_ssl(session_data->bev);
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
#endif /* !OPENSSL_NO_NEXTPROTONEG */
if (alpn == NULL) {
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
}

View File

@@ -106,21 +106,6 @@ struct app_context {
struct event_base *evbase;
};
static unsigned char next_proto_list[256];
static size_t next_proto_list_len;
#ifndef OPENSSL_NO_NEXTPROTONEG
static int next_proto_cb(SSL *ssl, const unsigned char **data,
unsigned int *len, void *arg) {
(void)ssl;
(void)arg;
*data = next_proto_list;
*len = (unsigned int)next_proto_list_len;
return SSL_TLSEXT_ERR_OK;
}
#endif /* !OPENSSL_NO_NEXTPROTONEG */
static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg) {
@@ -175,15 +160,6 @@ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
errx(1, "Could not read certificate file %s", cert_file);
}
next_proto_list[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
memcpy(&next_proto_list[1], NGHTTP2_PROTO_VERSION_ID,
NGHTTP2_PROTO_VERSION_ID_LEN);
next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
#endif /* !OPENSSL_NO_NEXTPROTONEG */
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
return ssl_ctx;
@@ -698,12 +674,7 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) {
ssl = bufferevent_openssl_get_ssl(session_data->bev);
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
#endif /* !OPENSSL_NO_NEXTPROTONEG */
if (alpn == NULL) {
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
}
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);

View File

@@ -5022,11 +5022,10 @@ NGHTTP2_EXTERN int nghttp2_nv_compare_name(const nghttp2_nv *lhs,
/**
* @function
*
* A helper function for dealing with NPN in client side or ALPN in
* server side. The |in| contains peer's protocol list in preferable
* order. The format of |in| is length-prefixed and not
* null-terminated. For example, ``h2`` and
* ``http/1.1`` stored in |in| like this::
* A helper function for dealing with ALPN in server side. The |in|
* contains peer's protocol list in preferable order. The format of
* |in| is length-prefixed and not null-terminated. For example,
* ``h2`` and ``http/1.1`` stored in |in| like this::
*
* in[0] = 2
* in[1..2] = "h2"
@@ -5051,20 +5050,18 @@ NGHTTP2_EXTERN int nghttp2_nv_compare_name(const nghttp2_nv *lhs,
*
* For ALPN, refer to https://tools.ietf.org/html/rfc7301
*
* See http://technotes.googlecode.com/git/nextprotoneg.html for more
* details about NPN.
* To use this method you should do something like::
*
* For NPN, to use this method you should do something like::
*
* static int select_next_proto_cb(SSL* ssl,
* unsigned char **out,
* static int alpn_select_proto_cb(SSL* ssl,
* const unsigned char **out,
* unsigned char *outlen,
* const unsigned char *in,
* unsigned int inlen,
* void *arg)
* {
* int rv;
* rv = nghttp2_select_next_protocol(out, outlen, in, inlen);
* rv = nghttp2_select_next_protocol((unsigned char**)out, outlen,
* in, inlen);
* if (rv == -1) {
* return SSL_TLSEXT_ERR_NOACK;
* }
@@ -5074,7 +5071,7 @@ NGHTTP2_EXTERN int nghttp2_nv_compare_name(const nghttp2_nv *lhs,
* return SSL_TLSEXT_ERR_OK;
* }
* ...
* SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, my_obj);
* SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, my_obj);
*
*/
NGHTTP2_EXTERN int nghttp2_select_next_protocol(unsigned char **out,

View File

@@ -725,7 +725,7 @@ int Http2Handler::tls_handshake() {
std::cerr << "SSL/TLS handshake completed" << std::endl;
}
if (verify_npn_result() != 0) {
if (verify_alpn_result() != 0) {
return -1;
}
@@ -892,25 +892,18 @@ int Http2Handler::connection_made() {
return on_write();
}
int Http2Handler::verify_npn_result() {
int Http2Handler::verify_alpn_result() {
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len;
// Check the negotiated protocol in NPN or ALPN
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl_, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
for (int i = 0; i < 2; ++i) {
if (next_proto) {
auto proto = StringRef{next_proto, next_proto_len};
if (sessions_->get_config()->verbose) {
std::cout << "The negotiated protocol: " << proto << std::endl;
}
if (util::check_h2_is_selected(proto)) {
return 0;
}
break;
} else {
SSL_get0_alpn_selected(ssl_, &next_proto, &next_proto_len);
// Check the negotiated protocol in ALPN
SSL_get0_alpn_selected(ssl_, &next_proto, &next_proto_len);
if (next_proto) {
auto proto = StringRef{next_proto, next_proto_len};
if (sessions_->get_config()->verbose) {
std::cout << "The negotiated protocol: " << proto << std::endl;
}
if (util::check_h2_is_selected(proto)) {
return 0;
}
}
if (sessions_->get_config()->verbose) {
@@ -1988,18 +1981,6 @@ HttpServer::HttpServer(const Config *config) : config_(config) {
};
}
#ifndef OPENSSL_NO_NEXTPROTONEG
namespace {
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
void *arg) {
auto next_proto = static_cast<std::vector<unsigned char> *>(arg);
*data = next_proto->data();
*len = next_proto->size();
return SSL_TLSEXT_ERR_OK;
}
} // namespace
#endif // !OPENSSL_NO_NEXTPROTONEG
namespace {
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
// We don't verify the client certificate. Just request it for the
@@ -2222,9 +2203,6 @@ int HttpServer::run() {
next_proto = util::get_default_alpn();
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, &next_proto);
#endif // !OPENSSL_NO_NEXTPROTONEG
// ALPN selection callback
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, this);
}

View File

@@ -167,7 +167,7 @@ public:
int on_read();
int on_write();
int connection_made();
int verify_npn_result();
int verify_alpn_result();
int submit_file_response(const StringRef &status, Stream *stream,
time_t last_modified, off_t file_length,

View File

@@ -1095,12 +1095,7 @@ int Client::connection_made() {
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
if (next_proto == nullptr) {
SSL_get0_alpn_selected(ssl, &next_proto, &next_proto_len);
}
SSL_get0_alpn_selected(ssl, &next_proto, &next_proto_len);
if (next_proto) {
auto proto = StringRef{next_proto, next_proto_len};
@@ -1130,9 +1125,8 @@ int Client::connection_made() {
for (const auto &proto : config.npn_list) {
if (util::streq(NGHTTP2_H1_1_ALPN, StringRef{proto})) {
std::cout
<< "Server does not support NPN/ALPN. Falling back to HTTP/1.1."
<< std::endl;
std::cout << "Server does not support ALPN. Falling back to HTTP/1.1."
<< std::endl;
session = std::make_unique<Http1Session>(this);
selected_proto = NGHTTP2_H1_1.str();
break;
@@ -1882,23 +1876,6 @@ std::string get_reqline(const char *uri, const http_parser_url &u) {
}
} // namespace
#ifndef OPENSSL_NO_NEXTPROTONEG
namespace {
int client_select_next_proto_cb(SSL *ssl, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg) {
if (util::select_protocol(const_cast<const unsigned char **>(out), outlen, in,
inlen, config.npn_list)) {
return SSL_TLSEXT_ERR_OK;
}
// OpenSSL will terminate handshake with fatal alert if we return
// NOACK. So there is no way to fallback.
return SSL_TLSEXT_ERR_NOACK;
}
} // namespace
#endif // !OPENSSL_NO_NEXTPROTONEG
namespace {
constexpr char UNIX_PATH_PREFIX[] = "unix:";
} // namespace
@@ -2273,10 +2250,9 @@ Options:
--npn-list=<LIST>
Comma delimited list of ALPN protocol identifier sorted
in the order of preference. That means most desirable
protocol comes first. This is used in both ALPN and
NPN. The parameter must be delimited by a single comma
only and any white spaces are treated as a part of
protocol string.
protocol comes first. The parameter must be delimited
by a single comma only and any white spaces are treated
as a part of protocol string.
Default: )"
<< DEFAULT_NPN_LIST << R"(
--h1 Short hand for --npn-list=http/1.1
@@ -2980,11 +2956,6 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE);
}
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ssl_ctx, client_select_next_proto_cb,
nullptr);
#endif // !OPENSSL_NO_NEXTPROTONEG
std::vector<unsigned char> proto_list;
for (const auto &proto : config.npn_list) {
std::copy_n(proto.c_str(), proto.size(), std::back_inserter(proto_list));

View File

@@ -127,7 +127,7 @@ struct Config {
bool base_uri_unix;
// used when UNIX domain socket is used (base_uri_unix is true).
sockaddr_un unix_addr;
// list of supported NPN/ALPN protocol strings in the order of
// list of supported ALPN protocol strings in the order of
// preference.
std::vector<std::string> npn_list;
// The number of request per second for each client.

View File

@@ -1115,24 +1115,19 @@ int HttpClient::connection_made() {
}
if (ssl) {
// Check NPN or ALPN result
// Check ALPN result
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
for (int i = 0; i < 2; ++i) {
if (next_proto) {
auto proto = StringRef{next_proto, next_proto_len};
if (config.verbose) {
std::cout << "The negotiated protocol: " << proto << std::endl;
}
if (!util::check_h2_is_selected(proto)) {
next_proto = nullptr;
}
break;
SSL_get0_alpn_selected(ssl, &next_proto, &next_proto_len);
if (next_proto) {
auto proto = StringRef{next_proto, next_proto_len};
if (config.verbose) {
std::cout << "The negotiated protocol: " << proto << std::endl;
}
if (!util::check_h2_is_selected(proto)) {
next_proto = nullptr;
}
SSL_get0_alpn_selected(ssl, &next_proto, &next_proto_len);
}
if (!next_proto) {
print_protocol_nego_error();
@@ -2242,32 +2237,6 @@ id responseEnd requestStart process code size request path)"
}
} // namespace
#ifndef OPENSSL_NO_NEXTPROTONEG
namespace {
int client_select_next_proto_cb(SSL *ssl, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg) {
if (config.verbose) {
print_timer();
std::cout << "[NPN] server offers:" << std::endl;
}
for (unsigned int i = 0; i < inlen; i += in[i] + 1) {
if (config.verbose) {
std::cout << " * ";
std::cout.write(reinterpret_cast<const char *>(&in[i + 1]), in[i]);
std::cout << std::endl;
}
}
if (!util::select_h2(const_cast<const unsigned char **>(out), outlen, in,
inlen)) {
print_protocol_nego_error();
return SSL_TLSEXT_ERR_NOACK;
}
return SSL_TLSEXT_ERR_OK;
}
} // namespace
#endif // !OPENSSL_NO_NEXTPROTONEG
namespace {
int communicate(
const std::string &scheme, const std::string &host, uint16_t port,
@@ -2338,10 +2307,6 @@ int communicate(
goto fin;
}
}
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ssl_ctx, client_select_next_proto_cb,
nullptr);
#endif // !OPENSSL_NO_NEXTPROTONEG
auto proto_list = util::get_default_alpn();

View File

@@ -2801,10 +2801,9 @@ SSL/TLS:
--npn-list=<LIST>
Comma delimited list of ALPN protocol identifier sorted
in the order of preference. That means most desirable
protocol comes first. This is used in both ALPN and
NPN. The parameter must be delimited by a single comma
only and any white spaces are treated as a part of
protocol string.
protocol comes first. The parameter must be delimited
by a single comma only and any white spaces are treated
as a part of protocol string.
Default: )"
<< DEFAULT_NPN_LIST
<< R"(

View File

@@ -616,12 +616,7 @@ int ClientHandler::validate_next_proto() {
// First set callback for catch all cases
on_read_ = &ClientHandler::upstream_read;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
if (next_proto == nullptr) {
SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len);
}
SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len);
StringRef proto;

View File

@@ -753,7 +753,7 @@ struct TLSConfig {
// The list of additional TLS certificate pair
std::vector<TLSCertificate> subcerts;
std::vector<unsigned char> alpn_prefs;
// list of supported NPN/ALPN protocol strings in the order of
// list of supported ALPN protocol strings in the order of
// preference.
std::vector<StringRef> npn_list;
// list of supported SSL/TLS protocol strings.

View File

@@ -794,12 +794,7 @@ int Connection::check_http2_requirement() {
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(tls.ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
if (next_proto == nullptr) {
SSL_get0_alpn_selected(tls.ssl, &next_proto, &next_proto_len);
}
SSL_get0_alpn_selected(tls.ssl, &next_proto, &next_proto_len);
if (next_proto == nullptr ||
!util::check_h2_is_selected(StringRef{next_proto, next_proto_len})) {
return 0;

View File

@@ -265,7 +265,7 @@ int ConnectionHandler::create_single_worker() {
nb_,
#endif // HAVE_NEVERBLEED
tlsconf.cacert, memcachedconf.cert_file,
memcachedconf.private_key_file, nullptr);
memcachedconf.private_key_file);
all_ssl_ctx_.push_back(session_cache_ssl_ctx);
#ifdef ENABLE_HTTP3
quic_all_ssl_ctx_.push_back(nullptr);
@@ -367,7 +367,7 @@ int ConnectionHandler::create_worker_thread(size_t num) {
nb_,
# endif // HAVE_NEVERBLEED
tlsconf.cacert, memcachedconf.cert_file,
memcachedconf.private_key_file, nullptr);
memcachedconf.private_key_file);
all_ssl_ctx_.push_back(session_cache_ssl_ctx);
# ifdef ENABLE_HTTP3
quic_all_ssl_ctx_.push_back(nullptr);
@@ -935,8 +935,7 @@ SSL_CTX *ConnectionHandler::create_tls_ticket_key_memcached_ssl_ctx() {
#ifdef HAVE_NEVERBLEED
nb_,
#endif // HAVE_NEVERBLEED
tlsconf.cacert, memcachedconf.cert_file, memcachedconf.private_key_file,
nullptr);
tlsconf.cacert, memcachedconf.cert_file, memcachedconf.private_key_file);
all_ssl_ctx_.push_back(ssl_ctx);
#ifdef ENABLE_HTTP3

View File

@@ -1672,12 +1672,7 @@ int Http2Session::connection_made() {
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len = 0;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
if (!next_proto) {
SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len);
}
SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len);
if (!next_proto) {
downstream_failure(addr_, raddr_);

View File

@@ -405,12 +405,7 @@ int LiveCheck::tls_handshake() {
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len = 0;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
if (next_proto == nullptr) {
SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len);
}
SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len);
auto proto = StringRef{next_proto, next_proto_len};

View File

@@ -96,18 +96,6 @@ namespace shrpx {
namespace tls {
#ifndef OPENSSL_NO_NEXTPROTONEG
namespace {
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
void *arg) {
auto &prefs = get_config()->tls.alpn_prefs;
*data = prefs.data();
*len = prefs.size();
return SSL_TLSEXT_ERR_OK;
}
} // namespace
#endif // !OPENSSL_NO_NEXTPROTONEG
namespace {
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
if (!preverify_ok) {
@@ -1065,10 +1053,6 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
SSL_CTX_set_early_data_enabled(ssl_ctx, 1);
#endif // NGHTTP2_OPENSSL_IS_BORINGSSL
// NPN advertisement
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, nullptr);
#endif // !OPENSSL_NO_NEXTPROTONEG
// ALPN selection callback
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, nullptr);
@@ -1384,62 +1368,12 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file,
}
#endif // ENABLE_HTTP3
namespace {
int select_h2_next_proto_cb(SSL *ssl, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg) {
if (!util::select_h2(const_cast<const unsigned char **>(out), outlen, in,
inlen)) {
return SSL_TLSEXT_ERR_NOACK;
}
return SSL_TLSEXT_ERR_OK;
}
} // namespace
namespace {
int select_h1_next_proto_cb(SSL *ssl, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg) {
auto end = in + inlen;
for (; in < end;) {
if (util::streq(NGHTTP2_H1_1_ALPN, StringRef{in, in + (in[0] + 1)})) {
*out = const_cast<unsigned char *>(in) + 1;
*outlen = in[0];
return SSL_TLSEXT_ERR_OK;
}
in += in[0] + 1;
}
return SSL_TLSEXT_ERR_NOACK;
}
} // namespace
namespace {
int select_next_proto_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
void *arg) {
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
switch (conn->proto) {
case Proto::HTTP1:
return select_h1_next_proto_cb(ssl, out, outlen, in, inlen, arg);
case Proto::HTTP2:
return select_h2_next_proto_cb(ssl, out, outlen, in, inlen, arg);
default:
return SSL_TLSEXT_ERR_NOACK;
}
}
} // namespace
SSL_CTX *create_ssl_client_context(
#ifdef HAVE_NEVERBLEED
neverbleed_t *nb,
#endif // HAVE_NEVERBLEED
const StringRef &cacert, const StringRef &cert_file,
const StringRef &private_key_file,
int (*next_proto_select_cb)(SSL *s, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg)) {
const StringRef &private_key_file) {
auto ssl_ctx = SSL_CTX_new(TLS_client_method());
if (!ssl_ctx) {
LOG(FATAL) << ERR_error_string(ERR_get_error(), nullptr);
@@ -1539,12 +1473,6 @@ SSL_CTX *create_ssl_client_context(
SSL_CTX_set_psk_client_callback(ssl_ctx, psk_client_cb);
#endif // !OPENSSL_NO_PSK
// NPN selection callback. This is required to set SSL_CTX because
// OpenSSL does not offer SSL_set_next_proto_select_cb.
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_cb, nullptr);
#endif // !OPENSSL_NO_NEXTPROTONEG
return ssl_ctx;
}
@@ -2249,8 +2177,8 @@ SSL_CTX *setup_downstream_client_ssl_context(
#ifdef HAVE_NEVERBLEED
nb,
#endif // HAVE_NEVERBLEED
tlsconf.cacert, tlsconf.client.cert_file, tlsconf.client.private_key_file,
select_next_proto_cb);
tlsconf.cacert, tlsconf.client.cert_file,
tlsconf.client.private_key_file);
}
void setup_downstream_http2_alpn(SSL *ssl) {

View File

@@ -89,28 +89,12 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
);
// Create client side SSL_CTX. This does not configure ALPN settings.
// |next_proto_select_cb| is for NPN.
SSL_CTX *create_ssl_client_context(
#ifdef HAVE_NEVERBLEED
neverbleed_t *nb,
#endif // HAVE_NEVERBLEED
const StringRef &cacert, const StringRef &cert_file,
const StringRef &private_key_file,
int (*next_proto_select_cb)(SSL *s, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg));
#ifdef ENABLE_HTTP3
SSL_CTX *create_quic_ssl_client_context(
# ifdef HAVE_NEVERBLEED
neverbleed_t *nb,
# endif // HAVE_NEVERBLEED
const StringRef &cacert, const StringRef &cert_file,
const StringRef &private_key_file,
int (*next_proto_select_cb)(SSL *s, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg));
#endif // ENABLE_HTTP3
const StringRef &private_key_file);
ClientHandler *accept_connection(Worker *worker, int fd, sockaddr *addr,
int addrlen, const UpstreamAddr *faddr);