ソースを参照

SSL set ALPN for http2

ithewei 3 年 前
コミット
f4529bfa07
3 ファイル変更49 行追加4 行削除
  1. 14 4
      http/server/HttpServer.cpp
  2. 4 0
      ssl/hssl.h
  3. 31 0
      ssl/openssl.c

+ 14 - 4
http/server/HttpServer.cpp

@@ -40,6 +40,12 @@ static void on_recv(hio_t* io, void* _buf, int readbytes) {
 
     HttpHandler::ProtocolType protocol = handler->protocol;
     if (protocol == HttpHandler::UNKNOWN) {
+        int http_version = 1;
+#if WITH_NGHTTP2
+        if (strncmp((char*)buf, HTTP2_MAGIC, MIN(readbytes, HTTP2_MAGIC_LEN)) == 0) {
+            http_version = 2;
+        }
+#else
         // check request-line
         if (readbytes < MIN_HTTP_REQUEST_LEN) {
             hloge("[%s:%d] http request-line too small", handler->ip, handler->port);
@@ -53,10 +59,7 @@ static void on_recv(hio_t* io, void* _buf, int readbytes) {
                 return;
             }
         }
-        int http_version = 1;
-        if (strncmp((char*)buf, HTTP2_MAGIC, MIN(readbytes, HTTP2_MAGIC_LEN)) == 0) {
-            http_version = 2;
-        }
+#endif
         if (!handler->Init(http_version, io)) {
             hloge("[%s:%d] unsupported HTTP%d", handler->ip, handler->port, http_version);
             hio_close(io);
@@ -334,6 +337,13 @@ int http_server_run(http_server_t* server, int wait) {
     }
     // https_port
     if (server->https_port > 0 && hssl_ctx_instance() != NULL) {
+#ifdef WITH_NGHTTP2
+#ifdef WITH_OPENSSL
+        static unsigned char s_alpn_protos[] = "\x02h2\x08http/1.1\x08http/1.0\x08http/0.9";
+        hssl_ctx_t ssl_ctx = hssl_ctx_instance();
+        hssl_ctx_set_alpn_protos(ssl_ctx, s_alpn_protos, sizeof(s_alpn_protos) - 1);
+#endif
+#endif
         server->listenfd[1] = Listen(server->https_port, server->host);
         if (server->listenfd[1] < 0) return server->listenfd[1];
         hlogi("https server listening on %s:%d", server->host, server->https_port);

+ 4 - 0
ssl/hssl.h

@@ -78,6 +78,10 @@ HV_EXPORT int hssl_close(hssl_t ssl);
 
 HV_EXPORT int hssl_set_sni_hostname(hssl_t ssl, const char* hostname);
 
+#ifdef WITH_OPENSSL
+HV_EXPORT int hssl_ctx_set_alpn_protos(hssl_ctx_t ssl_ctx, const unsigned char* protos, unsigned int protos_len);
+#endif
+
 END_EXTERN_C
 
 #endif // HV_SSL_H_

+ 31 - 0
ssl/openssl.c

@@ -154,4 +154,35 @@ int hssl_set_sni_hostname(hssl_t ssl, const char* hostname) {
     return 0;
 }
 
+#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
+static int hssl_ctx_alpn_select_cb(SSL *ssl,
+    const unsigned char **out, unsigned char *outlen,
+    const unsigned char *in, unsigned int inlen,
+    void *arg) {
+    const unsigned char* protos = (unsigned char*)arg;
+    unsigned int protos_len = strlen((char*)protos);
+    // printf("hssl_ctx_alpn_select_cb(in=%*.s:%u out=%.*s:%u protos=%.*s:%u)\n", inlen, in, inlen, (int)*outlen, (char*)out, (int)*outlen, protos_len, protos, protos_len);
+    if (SSL_select_next_proto((unsigned char **) out, outlen, protos, protos_len, in, inlen) != OPENSSL_NPN_NEGOTIATED) {
+        fprintf(stderr, "SSL_select_next_proto failed!\n");
+        return SSL_TLSEXT_ERR_ALERT_FATAL;
+    }
+    // printf("SSL_select_next_proto(out=%.*s:%u)\n", (int)*outlen, (char*)*out, (int)*outlen);
+    return SSL_TLSEXT_ERR_OK;
+}
+#endif
+
+int hssl_ctx_set_alpn_protos(hssl_ctx_t ssl_ctx, const unsigned char* protos, unsigned int protos_len) {
+    int ret = -1;
+    // printf("hssl_ctx_set_alpn_protos(%.*s:%u)\n", protos_len, protos, protos_len);
+#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
+    // for HSSL_CLIENT
+    // ret = SSL_CTX_set_alpn_protos((SSL_CTX*)ssl_ctx, (const unsigned char*)protos, protos_len);
+
+    // for HSSL_SERVER
+    SSL_CTX_set_alpn_select_cb((SSL_CTX*)ssl_ctx, hssl_ctx_alpn_select_cb, (void*)protos);
+    ret = 0;
+#endif
+    return ret;
+}
+
 #endif // WITH_OPENSSL