From: Matus Fabian Date: Tue, 20 May 2025 14:42:39 +0000 (+0000) Subject: http: starting tls connection with alpn X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F90%2F42990%2F5;p=vpp.git http: starting tls connection with alpn this patch also enable http/2 Type: improvement Change-Id: I20532ff6e3c4f7c4a45e889714a96ee874848fe4 Signed-off-by: Matus Fabian --- diff --git a/extras/hs-test/http2_test.go b/extras/hs-test/http2_test.go index 747f517ada3..8bcca1611a0 100644 --- a/extras/hs-test/http2_test.go +++ b/extras/hs-test/http2_test.go @@ -9,7 +9,7 @@ import ( ) func init() { - RegisterH2Tests(Http2TcpGetTest, Http2TcpPostTest, Http2MultiplexingTest, Http2MultiplexingMTTest) + RegisterH2Tests(Http2TcpGetTest, Http2TcpPostTest, Http2MultiplexingTest, Http2MultiplexingMTTest, Http2TlsTest) } func Http2TcpGetTest(s *H2Suite) { @@ -92,3 +92,16 @@ func Http2MultiplexingMTTest(s *H2Suite) { s.AssertContains(o, " 0 errored") s.AssertContains(o, " 0 timeout") } + +func Http2TlsTest(s *H2Suite) { + vpp := s.Containers.Vpp.VppInstance + serverAddress := s.VppAddr() + s.Log(vpp.Vppctl("http static server uri tls://" + serverAddress + "/443 url-handlers debug")) + + args := fmt.Sprintf("--max-time 10 --noproxy '*' -k https://%s:443/version.json", serverAddress) + writeOut, log := s.RunCurlContainer(s.Containers.Curl, args) + s.Log(vpp.Vppctl("show session verbose 2")) + s.AssertContains(log, "HTTP/2 200") + s.AssertContains(log, "ALPN: server accepted h2") + s.AssertContains(writeOut, "version") +} diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go index 66f6adaae8c..37bdecff240 100644 --- a/extras/hs-test/http_test.go +++ b/extras/hs-test/http_test.go @@ -1132,6 +1132,7 @@ func HttpStaticBuildInUrlGetVersionTest(s *NoTopoSuite) { defer resp.Body.Close() s.Log(DumpHttpResp(resp, true)) s.AssertHttpStatus(resp, 200) + s.AssertEqual(1, resp.ProtoMajor) data, err := io.ReadAll(resp.Body) s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(string(data), "vpp_details") diff --git a/extras/hs-test/infra/suite_h2.go b/extras/hs-test/infra/suite_h2.go index 7cf7a6b43ef..04919ad784a 100644 --- a/extras/hs-test/infra/suite_h2.go +++ b/extras/hs-test/infra/suite_h2.go @@ -76,7 +76,7 @@ func (s *H2Suite) VppAddr() string { } // Marked as pending since http plugin is not build with http/2 enabled by default -var _ = Describe("Http2Suite", Pending, Ordered, ContinueOnFailure, func() { +var _ = Describe("Http2Suite", Ordered, ContinueOnFailure, func() { var s H2Suite BeforeAll(func() { s.SetupSuite() @@ -170,8 +170,7 @@ var hpackTests = []h2specTest{ var http2Tests = []h2specTest{ {desc: "http2/3.5/1"}, - // TODO: need to be tested with TLS, otherwise we consider invalid preface as bogus HTTP/1 request - // {desc: "http2/3.5/2"}, + {desc: "http2/3.5/2"}, {desc: "http2/4.1/1"}, {desc: "http2/4.1/2"}, {desc: "http2/4.1/3"}, @@ -298,7 +297,7 @@ var specs = []struct { } // Marked as pending since http plugin is not build with http/2 enabled by default -var _ = Describe("H2SpecSuite", Pending, Ordered, ContinueOnFailure, func() { +var _ = Describe("H2SpecSuite", Ordered, ContinueOnFailure, func() { var s H2Suite BeforeAll(func() { s.SetupSuite() @@ -321,15 +320,15 @@ var _ = Describe("H2SpecSuite", Pending, Ordered, ContinueOnFailure, func() { s.Log(testName + ": BEGIN") vpp := s.Containers.Vpp.VppInstance serverAddress := s.VppAddr() - s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug 2")) + s.Log(vpp.Vppctl("http static server uri tls://" + serverAddress + "/443 url-handlers debug 2")) s.Log(vpp.Vppctl("test-url-handler enable")) conf := &config.Config{ Host: serverAddress, - Port: 80, + Port: 443, Path: "/test1", Timeout: time.Second * 5, MaxHeaderLen: 1024, - TLS: false, + TLS: true, Insecure: true, Sections: []string{test.desc}, Verbose: true, diff --git a/src/plugins/http/CMakeLists.txt b/src/plugins/http/CMakeLists.txt index ca2c0a9dc05..f5dabe20729 100644 --- a/src/plugins/http/CMakeLists.txt +++ b/src/plugins/http/CMakeLists.txt @@ -11,11 +11,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -option(VPP_ENABLE_HTTP_2 "Build http plugin with HTTP/2 enabled" OFF) -if(VPP_ENABLE_HTTP_2) - add_compile_definitions(HTTP_2_ENABLE=1) -endif() - add_vpp_plugin(http SOURCES http2/hpack.c diff --git a/src/plugins/http/http.c b/src/plugins/http/http.c index bf43ab0f6bb..876b7d2c9e5 100644 --- a/src/plugins/http/http.c +++ b/src/plugins/http/http.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -438,6 +439,7 @@ http_ts_accept_callback (session_t *ts) u32 hc_index, thresh; http_conn_handle_t hc_handle; transport_proto_t tp; + tls_alpn_proto_t alpn_proto; ts_listener = listen_session_get_from_handle (ts->listener_handle); lhc = http_listener_get (ts_listener->opaque); @@ -457,14 +459,30 @@ http_ts_accept_callback (session_t *ts) tp = session_get_transport_proto (ts); if (tp == TRANSPORT_PROTO_TLS) { - /* TODO: set by ALPN result */ - hc->version = HTTP_VERSION_1; + alpn_proto = tls_get_alpn_selected (ts->connection_index); + HTTP_DBG (1, "ALPN selected: %U", format_tls_alpn_proto, alpn_proto); + switch (alpn_proto) + { + case TLS_ALPN_PROTO_HTTP_2: + hc->version = HTTP_VERSION_2; + http_vfts[hc->version].conn_accept_callback (hc); + break; + case TLS_ALPN_PROTO_HTTP_1_1: + case TLS_ALPN_PROTO_NONE: + hc->version = HTTP_VERSION_1; + break; + default: + ASSERT (0); + return -1; + } } else { /* going to decide in http_ts_rx_callback */ hc->version = HTTP_VERSION_NA; } + + HTTP_DBG (1, "identified HTTP/%u", hc->version == HTTP_VERSION_1 ? 1 : 2); hc_handle.version = hc->version; hc_handle.conn_index = hc_index; ts->opaque = hc_handle.as_u32; @@ -492,6 +510,8 @@ http_ts_connected_callback (u32 http_app_index, u32 ho_hc_index, session_t *ts, http_conn_t *hc, *ho_hc; app_worker_t *app_wrk; http_conn_handle_t hc_handle; + transport_proto_t tp; + tls_alpn_proto_t alpn_proto; int rv; ho_hc = http_ho_conn_get (ho_hc_index); @@ -524,7 +544,29 @@ http_ts_connected_callback (u32 http_app_index, u32 ho_hc_index, session_t *ts, hc->state = HTTP_CONN_STATE_ESTABLISHED; ts->session_state = SESSION_STATE_READY; hc->flags |= HTTP_CONN_F_NO_APP_SESSION; - /* TODO: TLS set by ALPN result, TCP: prior knowledge (set in ho) */ + tp = session_get_transport_proto (ts); + /* TLS set by ALPN result, TCP: prior knowledge (set in ho) */ + if (tp == TRANSPORT_PROTO_TLS) + { + alpn_proto = tls_get_alpn_selected (ts->connection_index); + HTTP_DBG (1, "ALPN selected: %U", format_tls_alpn_proto, alpn_proto); + switch (alpn_proto) + { + case TLS_ALPN_PROTO_HTTP_2: + hc->version = HTTP_VERSION_2; + http_vfts[hc->version].conn_accept_callback (hc); + break; + case TLS_ALPN_PROTO_HTTP_1_1: + case TLS_ALPN_PROTO_NONE: + hc->version = HTTP_VERSION_1; + break; + default: + ASSERT (0); + return -1; + } + } + + HTTP_DBG (1, "identified HTTP/%u", hc->version == HTTP_VERSION_1 ? 1 : 2); hc_handle.version = hc->version; hc_handle.conn_index = new_hc_index; ts->opaque = hc_handle.as_u32; @@ -617,14 +659,8 @@ http_ts_rx_callback (session_t *ts) if (memcmp (rx_buf, http2_conn_preface.base, http2_conn_preface.len) == 0) { -#if HTTP_2_ENABLE > 0 hc->version = HTTP_VERSION_2; http_vfts[hc->version].conn_accept_callback (hc); -#else - svm_fifo_dequeue_drop_all (ts->rx_fifo); - http_disconnect_transport (hc); - return 0; -#endif } else hc->version = HTTP_VERSION_1; @@ -920,6 +956,13 @@ http_start_listen (u32 app_listener_index, transport_endpoint_cfg_t *tep) { HTTP_DBG (1, "app set tls"); tp = TRANSPORT_PROTO_TLS; + if (ext_cfg->crypto.alpn_protos[0] == TLS_ALPN_PROTO_NONE) + { + HTTP_DBG (1, + "app do not set alpn list, using default (h2,http/1.1)"); + ext_cfg->crypto.alpn_protos[0] = TLS_ALPN_PROTO_HTTP_2; + ext_cfg->crypto.alpn_protos[1] = TLS_ALPN_PROTO_HTTP_1_1; + } } args->sep_ext.transport_proto = tp; diff --git a/src/plugins/http/http2/http2.c b/src/plugins/http/http2/http2.c index 00974218fec..38a3cca4f82 100644 --- a/src/plugins/http/http2/http2.c +++ b/src/plugins/http/http2/http2.c @@ -8,10 +8,6 @@ #include #include -#ifndef HTTP_2_ENABLE -#define HTTP_2_ENABLE 0 -#endif - #define HTTP2_WIN_SIZE_MAX 0x7FFFFFFF #define HTTP2_INITIAL_WIN_SIZE 65535 /* connection-level flow control window kind of mirrors TCP flow control */ @@ -1966,8 +1962,6 @@ http2_init (vlib_main_t *vm) return 0; } -#if HTTP_2_ENABLE > 0 VLIB_INIT_FUNCTION (http2_init) = { .runs_after = VLIB_INITS ("http_transport_init"), }; -#endif