diff --git a/apisix/init.lua b/apisix/init.lua index 9fb8fc4c3496..16fd13ac7035 100644 --- a/apisix/init.lua +++ b/apisix/init.lua @@ -188,11 +188,12 @@ function _M.http_ssl_phase() end function _M.http_ssl_protocols_phase() - local ssl_clt = require "ngx.ssl.clienthello" - local host, err = ssl_clt.get_client_hello_server_name() - - if err then - core.log.error("failed to get the SNI name: ", err) + local sni, err = apisix_ssl.server_name(true) + if not sni or type(sni) ~= "string" then + local advise = "please check if the client requests via IP or uses an outdated " .. + "protocol. If you need to report an issue, " .. + "provide a packet capture file of the TLS handshake." + core.log.error("failed to find SNI: " .. (err or advise)) ngx_exit(-1) end @@ -200,7 +201,7 @@ function _M.http_ssl_protocols_phase() local api_ctx = core.tablepool.fetch("api_ctx", 0, 32) ngx_ctx.api_ctx = api_ctx - local ok, err = router.router_ssl.match_and_set(api_ctx, true, host) + local ok, err = router.router_ssl.match_and_set(api_ctx, true, sni) ngx_ctx.matched_ssl = api_ctx.matched_ssl core.tablepool.release("api_ctx", api_ctx) @@ -213,9 +214,10 @@ function _M.http_ssl_protocols_phase() ngx_exit(-1) end - local ssl_protocols = ngx_ctx.matched_ssl.value.ssl_protocols - if ssl_protocols then - ssl_clt.set_protocols(ssl_protocols) + ok ,err = apisix_ssl.set_protocols_by_clienthello(ngx_ctx.matched_ssl.value.ssl_protocols) + if not ok then + core.log.error("failed to set ssl protocols: ", err) + ngx_exit(-1) end end diff --git a/apisix/ssl.lua b/apisix/ssl.lua index 8bcdec0ffa90..447cb467adc6 100644 --- a/apisix/ssl.lua +++ b/apisix/ssl.lua @@ -14,9 +14,10 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -- -local core = require("apisix.core") -local ngx_ssl = require("ngx.ssl") -local secret = require("apisix.secret") +local core = require("apisix.core") +local ngx_ssl = require("ngx.ssl") +local secret = require("apisix.secret") +local ngx_ssl_client = require("ngx.ssl.clienthello") local ngx_encode_base64 = ngx.encode_base64 local ngx_decode_base64 = ngx.decode_base64 local aes = require("resty.aes") @@ -38,8 +39,14 @@ local pkey_cache = core.lrucache.new { local _M = {} -function _M.server_name() - local sni, err = ngx_ssl.server_name() +function _M.server_name(clienthello) + local sni, err + if clienthello then + sni, err = ngx_ssl_client.get_client_hello_server_name() + else + sni, err = ngx_ssl.server_name() + + end if err then return nil, err end @@ -56,6 +63,12 @@ function _M.server_name() return sni end +function _M.set_protocols_by_clienthello(ssl_protocols) + if ssl_protocols then + return ngx_ssl_client.set_protocols(ssl_protocols) + end + return true +end local function init_iv_tbl(ivs) local _aes_128_cbc_with_iv_tbl = core.table.new(2, 0) diff --git a/docs/en/latest/config.json b/docs/en/latest/config.json index 64e717c1bc3b..26e56a30501a 100644 --- a/docs/en/latest/config.json +++ b/docs/en/latest/config.json @@ -366,6 +366,10 @@ { "type": "doc", "id": "profile" + }, + { + "type": "doc", + "id": "ssl-protocol" } ] }, diff --git a/docs/zh/latest/config.json b/docs/zh/latest/config.json index 98db5b6a810f..bbb7458f40ce 100644 --- a/docs/zh/latest/config.json +++ b/docs/zh/latest/config.json @@ -300,6 +300,10 @@ { "type": "doc", "id": "profile" + }, + { + "type": "doc", + "id": "ssl-protocol" } ] }, diff --git a/t/node/ssl-protocols.t b/t/node/ssl-protocols.t index c1ac5836a5ed..1edd17c9d28b 100644 --- a/t/node/ssl-protocols.t +++ b/t/node/ssl-protocols.t @@ -21,6 +21,8 @@ log_level('info'); no_root_location(); no_shuffle(); +$ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); + add_block_preprocessor(sub { my ($block) = @_; @@ -286,3 +288,46 @@ qr/TLSv1\.1 \(IN\), TLS handshake, Server hello(?s).*hello world/ curl -k -v --tls-max 1.3 --tlsv1.3 --resolve "test.com:1994:127.0.0.1" https://test.com:1994/hello 2>&1 | cat --- response_body eval qr/TLSv1\.3 \(IN\), TLS alert/ + + + +=== TEST 15: hello +--- config +listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + +location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + local ssl = require "ssl" + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + local params = { + mode = "client", + protocol = "tlsv1_3", + verify = "none", + options = "all", + } + local sec_sock = ssl.wrap(sock, params) + + local sess, err = sec_sock:dohandshake() + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + ngx.say("ssl handshake: ", sess ~= nil) + end -- do + -- collectgarbage() + } +} +--- request +GET /t +--- response_body +ssl handshake: true diff --git a/t/router/radixtree-sni2.t b/t/router/radixtree-sni2.t index c64a20aae344..c761c9043d45 100644 --- a/t/router/radixtree-sni2.t +++ b/t/router/radixtree-sni2.t @@ -405,7 +405,7 @@ location /t { --- response_body failed to do SSL handshake: handshake failed --- error_log -failed to fetch ssl config: failed to find SNI: please check if the client requests via IP or uses an outdated protocol +failed to find SNI: please check if the client requests via IP or uses an outdated protocol --- no_error_log [alert]