Skip to content

Commit ceb95da

Browse files
authored
feat: add support for wildcard on SNIs for SSL (#12668)
1 parent fb99852 commit ceb95da

File tree

3 files changed

+290
-2
lines changed

3 files changed

+290
-2
lines changed

apisix/schema_def.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ local id_schema = {
3939
}
4040
}
4141

42-
local host_def_pat = "^\\*?[0-9a-zA-Z-._\\[\\]:]+$"
42+
local host_def_pat = "^\\*$|^\\*?[0-9a-zA-Z-._\\[\\]:]+$"
4343
local host_def = {
4444
type = "string",
4545
pattern = host_def_pat,

apisix/ssl/router/radixtree_sni.lua

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,10 @@ function _M.match_and_set(api_ctx, match_only, alt_sni)
181181
end
182182

183183

184-
if type(api_ctx.matched_sni) == "table" then
184+
if api_ctx.matched_sni == "*" then
185+
-- wildcard matches everything, no need for further validation
186+
core.log.info("matched wildcard SSL for SNI: ", sni)
187+
elseif type(api_ctx.matched_sni) == "table" then
185188
local matched = false
186189
for _, msni in ipairs(api_ctx.matched_sni) do
187190
if sni_rev == msni or not str_find(sni_rev, ".", #msni) then

t/stream-node/sni.t

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,288 @@ proxy request to 127.0.0.3:1995
339339
}
340340
--- request
341341
GET /t
342+
343+
344+
345+
=== TEST 14: set SSL with wildcard * SNI and test route matching
346+
--- config
347+
location /t {
348+
content_by_lua_block {
349+
local core = require("apisix.core")
350+
local t = require("lib.test_admin")
351+
352+
local ssl_cert = t.read_file("t/certs/apisix.crt")
353+
local ssl_key = t.read_file("t/certs/apisix.key")
354+
355+
-- Create SSL with wildcard * SNI (catch-all)
356+
local data = {
357+
cert = ssl_cert,
358+
key = ssl_key,
359+
sni = "*", -- Wildcard catch-all
360+
}
361+
362+
local code, body = t.test('/apisix/admin/ssls/100',
363+
ngx.HTTP_PUT,
364+
core.json.encode(data)
365+
)
366+
367+
if code >= 300 then
368+
ngx.status = code
369+
ngx.say("failed to create wildcard SSL: ", code, " ", body)
370+
return
371+
end
372+
373+
-- Create a stream route that will use the wildcard SSL
374+
local code, body = t.test('/apisix/admin/stream_routes/100',
375+
ngx.HTTP_PUT,
376+
[[{
377+
"sni": "unknown-domain.com",
378+
"upstream": {
379+
"nodes": {
380+
"127.0.0.1:1995": 1
381+
},
382+
"type": "roundrobin"
383+
}
384+
}]]
385+
)
386+
387+
if code >= 300 then
388+
ngx.status = code
389+
ngx.say("failed to create stream route: ", code, " ", body)
390+
return
391+
end
392+
393+
ngx.say("passed")
394+
}
395+
}
396+
--- request
397+
GET /t
398+
--- response_body
399+
passed
400+
401+
402+
403+
=== TEST 15: hit route with unknown domain using wildcard SSL
404+
--- stream_tls_request
405+
mmm
406+
--- stream_sni: unknown-domain.com
407+
--- response_body
408+
hello world
409+
--- error_log
410+
proxy request to 127.0.0.1:1995
411+
412+
413+
414+
=== TEST 16: test SSL priority - exact match over partial wildcard
415+
--- config
416+
location /t {
417+
content_by_lua_block {
418+
local core = require("apisix.core")
419+
local t = require("lib.test_admin")
420+
421+
local ssl_cert = t.read_file("t/certs/apisix.crt")
422+
local ssl_key = t.read_file("t/certs/apisix.key")
423+
424+
-- Create SSL with exact domain match
425+
local data = {
426+
cert = ssl_cert,
427+
key = ssl_key,
428+
sni = "specific.api7.dev",
429+
}
430+
431+
local code, body = t.test('/apisix/admin/ssls/101',
432+
ngx.HTTP_PUT,
433+
core.json.encode(data)
434+
)
435+
436+
if code >= 300 then
437+
ngx.status = code
438+
ngx.say("failed to create exact SSL: ", code, " ", body)
439+
return
440+
end
441+
442+
-- Create SSL with partial wildcard
443+
local data = {
444+
cert = ssl_cert,
445+
key = ssl_key,
446+
sni = "*.api7.dev",
447+
}
448+
449+
local code, body = t.test('/apisix/admin/ssls/102',
450+
ngx.HTTP_PUT,
451+
core.json.encode(data)
452+
)
453+
454+
if code >= 300 then
455+
ngx.status = code
456+
ngx.say("failed to create partial wildcard SSL: ", code, " ", body)
457+
return
458+
end
459+
460+
-- Create routes for testing
461+
local code, body = t.test('/apisix/admin/stream_routes/101',
462+
ngx.HTTP_PUT,
463+
[[{
464+
"sni": "specific.api7.dev",
465+
"upstream": {
466+
"nodes": {
467+
"127.0.0.1:1995": 1
468+
},
469+
"type": "roundrobin"
470+
}
471+
}]]
472+
)
473+
474+
if code >= 300 then
475+
ngx.status = code
476+
ngx.say("failed to create exact route: ", code, " ", body)
477+
return
478+
end
479+
480+
local code, body = t.test('/apisix/admin/stream_routes/102',
481+
ngx.HTTP_PUT,
482+
[[{
483+
"sni": "*.api7.dev",
484+
"upstream": {
485+
"nodes": {
486+
"127.0.0.2:1995": 1
487+
},
488+
"type": "roundrobin"
489+
}
490+
}]]
491+
)
492+
493+
if code >= 300 then
494+
ngx.status = code
495+
ngx.say("failed to create partial wildcard route: ", code, " ", body)
496+
return
497+
end
498+
499+
ngx.say("passed")
500+
}
501+
}
502+
--- request
503+
GET /t
504+
--- response_body
505+
passed
506+
507+
508+
509+
=== TEST 17: verify exact domain takes priority over partial wildcard
510+
--- stream_tls_request
511+
mmm
512+
--- stream_sni: specific.api7.dev
513+
--- response_body
514+
hello world
515+
--- error_log
516+
proxy request to 127.0.0.1:1995
517+
--- no_error_log
518+
proxy request to 127.0.0.2:1995
519+
520+
521+
522+
=== TEST 18: test SSL priority - partial match over wildcard
523+
--- config
524+
location /t {
525+
content_by_lua_block {
526+
local core = require("apisix.core")
527+
local t = require("lib.test_admin")
528+
529+
local ssl_cert = t.read_file("t/certs/apisix.crt")
530+
local ssl_key = t.read_file("t/certs/apisix.key")
531+
532+
-- Create SSL with partial domain match
533+
local data = {
534+
cert = ssl_cert,
535+
key = ssl_key,
536+
sni = "specific.api7.dev",
537+
}
538+
539+
local code, body = t.test('/apisix/admin/ssls/101',
540+
ngx.HTTP_PUT,
541+
core.json.encode(data)
542+
)
543+
544+
if code >= 300 then
545+
ngx.status = code
546+
ngx.say("failed to create exact SSL: ", code, " ", body)
547+
return
548+
end
549+
550+
-- Create SSL with wildcard
551+
local data = {
552+
cert = ssl_cert,
553+
key = ssl_key,
554+
sni = "*",
555+
}
556+
557+
local code, body = t.test('/apisix/admin/ssls/102',
558+
ngx.HTTP_PUT,
559+
core.json.encode(data)
560+
)
561+
562+
if code >= 300 then
563+
ngx.status = code
564+
ngx.say("failed to create partial wildcard SSL: ", code, " ", body)
565+
return
566+
end
567+
568+
-- Create routes for testing
569+
local code, body = t.test('/apisix/admin/stream_routes/101',
570+
ngx.HTTP_PUT,
571+
[[{
572+
"sni": "*.api7.dev",
573+
"upstream": {
574+
"nodes": {
575+
"127.0.0.1:1995": 1
576+
},
577+
"type": "roundrobin"
578+
}
579+
}]]
580+
)
581+
582+
if code >= 300 then
583+
ngx.status = code
584+
ngx.say("failed to create exact route: ", code, " ", body)
585+
return
586+
end
587+
588+
local code, body = t.test('/apisix/admin/stream_routes/102',
589+
ngx.HTTP_PUT,
590+
[[{
591+
"sni": "*",
592+
"upstream": {
593+
"nodes": {
594+
"127.0.0.2:1995": 1
595+
},
596+
"type": "roundrobin"
597+
}
598+
}]]
599+
)
600+
601+
if code >= 300 then
602+
ngx.status = code
603+
ngx.say("failed to create partial wildcard route: ", code, " ", body)
604+
return
605+
end
606+
607+
ngx.say("passed")
608+
}
609+
}
610+
--- request
611+
GET /t
612+
--- response_body
613+
passed
614+
615+
616+
617+
=== TEST 19: verify partial match takes priority over wildcard
618+
--- stream_tls_request
619+
mmm
620+
--- stream_sni: specific.api7.dev
621+
--- response_body
622+
hello world
623+
--- error_log
624+
proxy request to 127.0.0.1:1995
625+
--- no_error_log
626+
proxy request to 127.0.0.2:1995

0 commit comments

Comments
 (0)