This is an automated email from the ASF dual-hosted git repository.
membphis pushed a commit to branch feat/ssl-session-ticket-takeover
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to
refs/heads/feat/ssl-session-ticket-takeover by this push:
new 57c36ab6a5 fix(ssl-session-ticket): record the first round of a worker
from a timer
57c36ab6a5 is described below
commit 57c36ab6a5e9cfe8ab649ed2b419b170ee5f2ce4
Author: Yuansheng Wang <[email protected]>
AuthorDate: Thu Oct 29 10:20:03 2026 +0800
fix(ssl-session-ticket): record the first round of a worker from a timer
init_worker cannot sleep: when every process of a reload writes its worker
record at once, the first write only spun on the lock of the state and could
time out ("failed to lock shared dict 'tls-session-ticket': timeout"). A
worker still applies the target at once, then records it from a timer.
t/stream-node/mtls.t replays a saved session under another SNI to check that
a resumed session cannot bypass the client verification. TEST 8 and 9 keep
the session cache of the previous Stream listener; TEST 10 to 12 replay a
ticket of the shared keys, the only way a Stream session resumes with a
runtime that takes over the keys: it is rejected the same way.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
apisix/ssl/session_ticket.lua | 16 ++++++++++--
t/stream-node/mtls.t | 59 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+), 2 deletions(-)
diff --git a/apisix/ssl/session_ticket.lua b/apisix/ssl/session_ticket.lua
index fcc52b7f7c..de9ce9f568 100644
--- a/apisix/ssl/session_ticket.lua
+++ b/apisix/ssl/session_ticket.lua
@@ -316,10 +316,22 @@ function _M.init_worker()
return
end
- tick()
+ -- Apply at once. Writing the record takes the lock of the state, which
+ -- may have to wait for the other processes, e.g. all of them during a
+ -- reload: init_worker cannot sleep, so in a timer.
+ _M.reconcile()
+ local ok, err = ngx.timer.at(0, function(premature)
+ if not premature then
+ tick()
+ end
+ end)
+ if not ok then
+ core.log.error("failed to create the first round of the TLS session
ticket keys: ",
+ err)
+ end
timers.register_timer(TIMER_NAME, tick)
- local ok, err = ngx.timer.every(EXIT_HOOK_INTERVAL, on_exit_hook)
+ ok, err = ngx.timer.every(EXIT_HOOK_INTERVAL, on_exit_hook)
if not ok then
core.log.error("failed to create the exit hook of the TLS session
ticket keys: ", err)
end
diff --git a/t/stream-node/mtls.t b/t/stream-node/mtls.t
index 9e1f2c9349..97d98d2fab 100644
--- a/t/stream-node/mtls.t
+++ b/t/stream-node/mtls.t
@@ -316,6 +316,9 @@ GET /t
=== TEST 8: request localhost and save tls session to reuse
+The session cache of the Stream listener, see TEST 10 for the shared
+session ticket keys.
+--- legacy_ssl_session_tickets
--- stream_enable
--- max_size: 1048576
--- exec
@@ -326,6 +329,7 @@ echo "" | timeout 1 openssl s_client -ign_eof -connect
127.0.0.1:2005 \
=== TEST 9: request test.com with saved tls session
+--- legacy_ssl_session_tickets
--- stream_enable
--- max_size: 1048576
--- exec
@@ -333,3 +337,58 @@ echo "" | openssl s_client -connect 127.0.0.1:2005
-servername test.com \
-sess_in session.dat
--- error_log
sni in client hello mismatch hostname of ssl session, sni: test.com, hostname:
localhost
+
+
+
+=== TEST 10: share the session ticket keys
+--- extra_yaml_config
+plugin_attr:
+ ssl-session-ticket:
+ enabled: true
+ key_source: external
+--- config
+ location /t {
+ content_by_lua_block {
+ local h = require("lib.ssl_session_ticket")
+ local code = h.put_keys(1)
+ h.wait_state(function(s) return s.keys[1] == h.key(1) end)
+ ngx.say(code < 300)
+ }
+ }
+--- request
+GET /t
+--- response_body
+true
+
+
+
+=== TEST 11: request localhost and save the tls session, a ticket of the
shared keys
+With a runtime that takes over the keys, the Stream listener resumes sessions
+with them only.
+--- extra_yaml_config
+plugin_attr:
+ ssl-session-ticket:
+ enabled: true
+ key_source: external
+--- stream_enable
+--- max_size: 1048576
+--- exec
+sleep 2; echo "" | timeout 1 openssl s_client -ign_eof -connect 127.0.0.1:2005
\
+ -servername localhost -cert t/certs/mtls_client.crt -key
t/certs/mtls_client.key \
+ -sess_out session.dat
+
+
+
+=== TEST 12: a shared ticket of another SNI does not bypass the client
verification
+--- extra_yaml_config
+plugin_attr:
+ ssl-session-ticket:
+ enabled: true
+ key_source: external
+--- stream_enable
+--- max_size: 1048576
+--- exec
+sleep 2; echo "" | openssl s_client -connect 127.0.0.1:2005 -servername
test.com \
+ -sess_in session.dat
+--- error_log
+sni in client hello mismatch hostname of ssl session, sni: test.com, hostname:
localhost