From ecf8d3e1df64ac9ff08b961e29c402b60fc7e3b7 Mon Sep 17 00:00:00 2001 From: Matus Fabian Date: Wed, 21 May 2025 16:49:20 +0000 Subject: [PATCH] http_static: add http1-only option to cli This option enable only HTTP/1.1 in TLS ALPN list Type: improvement Change-Id: If39e50b25b727533477a80182f96cd9876505762 Signed-off-by: Matus Fabian --- extras/hs-test/http_test.go | 21 ++++++++++++++++++++- src/plugins/http_static/http_static.h | 2 ++ src/plugins/http_static/static_server.c | 18 +++++++++++++----- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go index 4f3e852ed62..f0a6f07cb63 100644 --- a/extras/hs-test/http_test.go +++ b/extras/hs-test/http_test.go @@ -37,7 +37,7 @@ func init() { HttpClientGetTlsNoRespBodyTest, HttpClientPostFileTest, HttpClientPostFilePtrTest, HttpUnitTest, HttpRequestLineTest, HttpClientGetTimeout, HttpStaticFileHandlerWrkTest, HttpStaticUrlHandlerWrkTest, HttpConnTimeoutTest, HttpClientGetRepeatTest, HttpClientPostRepeatTest, HttpIgnoreH2UpgradeTest, HttpInvalidAuthorityFormUriTest, HttpHeaderErrorConnectionDropTest, - HttpClientInvalidHeaderNameTest) + HttpClientInvalidHeaderNameTest, HttpStaticHttp1OnlyTest) RegisterNoTopoSoloTests(HttpStaticPromTest, HttpGetTpsTest, HttpGetTpsInterruptModeTest, PromConcurrentConnectionsTest, PromMemLeakTest, HttpClientPostMemLeakTest, HttpInvalidClientRequestMemLeakTest, HttpPostTpsTest, HttpPostTpsInterruptModeTest, PromConsecutiveConnectionsTest, HttpGetTpsTlsTest, HttpPostTpsTlsTest, HttpClientGetRepeatMTTest, HttpClientPtrGetRepeatMTTest) @@ -1167,6 +1167,25 @@ func HttpCliBadRequestTest(s *NoTopoSuite) { s.AssertHttpContentLength(resp, int64(0)) } +func HttpStaticHttp1OnlyTest(s *NoTopoSuite) { + vpp := s.Containers.Vpp.VppInstance + serverAddress := s.VppAddr() + s.Log(vpp.Vppctl("http static server uri tls://" + serverAddress + "/80 url-handlers http1-only debug")) + + client := NewHttpClient(defaultHttpTimeout, true) + req, err := http.NewRequest("GET", "https://"+serverAddress+":80/version.json", nil) + s.AssertNil(err, fmt.Sprint(err)) + resp, err := client.Do(req) + s.AssertNil(err, fmt.Sprint(err)) + 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), "version") +} + func HttpStaticBuildInUrlGetVersionTest(s *NoTopoSuite) { vpp := s.Containers.Vpp.VppInstance serverAddress := s.VppAddr() diff --git a/src/plugins/http_static/http_static.h b/src/plugins/http_static/http_static.h index 2b5c065e287..2c65df0c9d0 100644 --- a/src/plugins/http_static/http_static.h +++ b/src/plugins/http_static/http_static.h @@ -156,6 +156,8 @@ typedef struct hss_listener_ u32 l_index; /** Listener session handle */ session_handle_t session_handle; + /** Enable only HTTP/1.1 in TLS ALPN list */ + u8 http1_only; } hss_listener_t; /** \brief Main data structure diff --git a/src/plugins/http_static/static_server.c b/src/plugins/http_static/static_server.c index 692cb53abe3..f1cfbeec1d7 100644 --- a/src/plugins/http_static/static_server.c +++ b/src/plugins/http_static/static_server.c @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -991,6 +992,8 @@ hss_listen (hss_listener_t *l, session_handle_t *lh) &a->sep_ext, TRANSPORT_ENDPT_EXT_CFG_CRYPTO, sizeof (transport_endpt_crypto_cfg_t)); ext_cfg->crypto.ckpair_index = hsm->ckpair_index; + if (l->http1_only) + ext_cfg->crypto.alpn_protos[0] = TLS_ALPN_PROTO_HTTP_1_1; } if (!(rv = vnet_listen (a))) @@ -1132,6 +1135,7 @@ hss_create_command_fn (vlib_main_t *vm, unformat_input_t *input, l->max_body_size = HSS_DEFAULT_MAX_BODY_SIZE; l->rx_buff_thresh = HSS_DEFAULT_RX_BUFFER_THRESH; l->keepalive_timeout = HSS_DEFAULT_KEEPALIVE_TIMEOUT; + l->http1_only = 0; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -1177,6 +1181,8 @@ hss_create_command_fn (vlib_main_t *vm, unformat_input_t *input, else if (unformat (line_input, "ptr-thresh %U", unformat_memory_size, &l->use_ptr_thresh)) ; + else if (unformat (line_input, "http1-only")) + l->http1_only = 1; else { error = clib_error_return (0, "unknown input `%U'", @@ -1235,9 +1241,10 @@ done: * @clistart * http static server www-root /tmp/www uri tcp://0.0.0.0/80 cache-size 2m * @cliend - * @cliexcmd{http static server www-root [prealloc-fios ] - * [private-segment-size ] [fifo-size ] [uri ] - * [keepalive-timeout ]} + * @cliexcmd{http static server www-root [url-handlers] + * [private-segment-size ] [fifo-size ] [max-age ] + * [uri ] [ptr-thresh ] [prealloc-fifos ] [debug [nn]] + * [keepalive-timeout ] [max-body-size ] [http1-only]} ?*/ VLIB_CLI_COMMAND (hss_create_command, static) = { .path = "http static server", @@ -1245,7 +1252,7 @@ VLIB_CLI_COMMAND (hss_create_command, static) = { "http static server [www-root ] [url-handlers]\n" "[private-segment-size ] [fifo-size ] [max-age ]\n" "[uri ] [ptr-thresh ] [prealloc-fifos ] [debug [nn]]\n" - "[keepalive-timeout ] [max-body-size ]\n", + "[keepalive-timeout ] [max-body-size ] [http1-only]\n", .function = hss_create_command_fn, }; @@ -1271,6 +1278,7 @@ hss_add_del_listener_command_fn (vlib_main_t *vm, unformat_input_t *input, l->max_body_size = HSS_DEFAULT_MAX_BODY_SIZE; l->rx_buff_thresh = HSS_DEFAULT_RX_BUFFER_THRESH; l->keepalive_timeout = HSS_DEFAULT_KEEPALIVE_TIMEOUT; + l->http1_only = 0; while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { @@ -1355,7 +1363,7 @@ done: VLIB_CLI_COMMAND (hss_add_del_listener_command, static) = { .path = "http static listener", .short_help = "http static listener [add|del] uri \n" - "[www-root ] [url-handlers] \n", + "[www-root ] [url-handlers] [http1-only]\n", .function = hss_add_del_listener_command_fn, }; -- 2.16.6