Skip to content

Commit 03d8883

Browse files
authored
feature: proxy_ssl_verify_by_lua directives.
1 parent eb2b57f commit 03d8883

12 files changed

+2446
-22
lines changed

README.markdown

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,8 @@ Directives
11711171
* [ssl_session_fetch_by_lua_file](#ssl_session_fetch_by_lua_file)
11721172
* [ssl_session_store_by_lua_block](#ssl_session_store_by_lua_block)
11731173
* [ssl_session_store_by_lua_file](#ssl_session_store_by_lua_file)
1174+
* [proxy_ssl_verify_by_lua_block](#proxy_ssl_verify_by_lua_block)
1175+
* [proxy_ssl_verify_by_lua_file](#proxy_ssl_verify_by_lua_file)
11741176
* [lua_shared_dict](#lua_shared_dict)
11751177
* [lua_socket_connect_timeout](#lua_socket_connect_timeout)
11761178
* [lua_socket_send_timeout](#lua_socket_send_timeout)
@@ -1189,6 +1191,7 @@ Directives
11891191
* [lua_ssl_verify_depth](#lua_ssl_verify_depth)
11901192
* [lua_ssl_key_log](#lua_ssl_key_log)
11911193
* [lua_ssl_conf_command](#lua_ssl_conf_command)
1194+
* [lua_upstream_skip_openssl_default_verify](#lua_upstream_skip_openssl_default_verify)
11921195
* [lua_http10_buffering](#lua_http10_buffering)
11931196
* [rewrite_by_lua_no_postpone](#rewrite_by_lua_no_postpone)
11941197
* [access_by_lua_no_postpone](#access_by_lua_no_postpone)
@@ -3165,6 +3168,84 @@ Note that: this directive is only allowed to used in **http context** from the `
31653168

31663169
[Back to TOC](#directives)
31673170

3171+
proxy_ssl_verify_by_lua_block
3172+
-----------------------------
3173+
3174+
**syntax:** *proxy_ssl_verify_by_lua_block { lua-script }*
3175+
3176+
**context:** *location*
3177+
3178+
**phase:** *right-after-server-certificate-message-was-processed*
3179+
3180+
This directive runs user Lua code when Nginx is about to post-process the SSL server certificate message for the upstream SSL (https) connections.
3181+
3182+
It is particularly useful to parse upstream server certificate and do some custom operations in pure lua.
3183+
3184+
The [ngx.ssl.proxysslverify](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl/proxysslverify.md) Lua modules provided by the [lua-resty-core](https://github.com/openresty/lua-resty-core/#readme)
3185+
library are particularly useful in this context.
3186+
3187+
Below is a trivial example using the
3188+
[ngx.ssl.proxysslverify](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl/proxysslverify.md) module
3189+
at the same time:
3190+
3191+
```nginx
3192+
3193+
server {
3194+
listen 443 ssl;
3195+
server_name test.com;
3196+
ssl_certificate /path/to/cert.crt;
3197+
ssl_certificate_key /path/to/key.key;
3198+
3199+
location /t {
3200+
proxy_ssl_certificate /path/to/cert.crt;
3201+
proxy_ssl_certificate_key /path/to/key.key;
3202+
proxy_pass https://upstream;
3203+
3204+
proxy_ssl_verify_by_lua_block {
3205+
local proxy_ssl_vfy = require "ngx.ssl.proxysslverify"
3206+
local cert = proxy_ssl_vfy.get_verify_cert()
3207+
3208+
-- ocsp to verify cert
3209+
-- check crl
3210+
proxy_ssl_vfy.set_verify_result()
3211+
...
3212+
}
3213+
}
3214+
...
3215+
}
3216+
```
3217+
3218+
See more information in the [ngx.ssl.proxysslverify](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl/proxysslverify.md)
3219+
Lua modules' official documentation.
3220+
3221+
Uncaught Lua exceptions in the user Lua code immediately abort the current SSL session, so does the
3222+
[ngx.exit](#ngxexit) call with an error code like `ngx.ERROR`.
3223+
3224+
This Lua code execution context *does* support yielding, so Lua APIs that may yield
3225+
(like cosockets, sleeping, and "light threads")
3226+
are enabled in this context
3227+
3228+
Note, `ngx.ctx` in proxy_ssl_verify_by_lua_block is belonging to upstream connection, not downstream connection, so it's different from `ngx.ctx` in contexts like ssl_certificate_by_lua etc.
3229+
3230+
This directive requires OpenSSL 3.0.2 or greater.
3231+
3232+
[Back to TOC](#directives)
3233+
3234+
proxy_ssl_verify_by_lua_file
3235+
----------------------------
3236+
3237+
**syntax:** *proxy_ssl_verify_by_lua_file <path-to-lua-script-file>*
3238+
3239+
**context:** *location*
3240+
3241+
**phase:** *right-after-server-certificate-message-was-processed*
3242+
3243+
Equivalent to [proxy_ssl_verify_by_lua_block](#proxy_ssl_verify_by_lua_block), except that the file specified by `<path-to-lua-script-file>` contains the Lua code, or, as from the `v0.5.0rc32` release, the [LuaJIT bytecode](#luajit-bytecode-support) to be executed.
3244+
3245+
When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server.
3246+
3247+
[Back to TOC](#directives)
3248+
31683249
lua_shared_dict
31693250
---------------
31703251

@@ -3499,6 +3580,21 @@ This directive was first introduced in the `v0.10.21` release.
34993580

35003581

35013582

3583+
[Back to TOC](#directives)
3584+
3585+
lua_upstream_skip_openssl_default_verify
3586+
--------------------
3587+
3588+
**syntax:** *lua_upstream_skip_openssl_default_verify on|off*
3589+
3590+
**default:** *lua_upstream_skip_openssl_default_verify off*
3591+
3592+
**context:** *location, location-if*
3593+
3594+
When using proxy_ssl_verify_by_lua directive, `lua_upstream_skip_openssl_default_verify` controls whether to skip default openssl's verify function, that means using pure Lua code to verify upstream server certificate.
3595+
3596+
This directive is turned `off` by default.
3597+
35023598
[Back to TOC](#directives)
35033599

35043600
lua_http10_buffering

config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ HTTP_LUA_SRCS=" \
296296
$ngx_addon_dir/src/ngx_http_lua_ssl_session_storeby.c \
297297
$ngx_addon_dir/src/ngx_http_lua_ssl_session_fetchby.c \
298298
$ngx_addon_dir/src/ngx_http_lua_ssl.c \
299+
$ngx_addon_dir/src/ngx_http_lua_proxy_ssl_verifyby.c \
299300
$ngx_addon_dir/src/ngx_http_lua_log_ringbuf.c \
300301
$ngx_addon_dir/src/ngx_http_lua_input_filters.c \
301302
$ngx_addon_dir/src/ngx_http_lua_pipe.c \
@@ -359,6 +360,7 @@ HTTP_LUA_DEPS=" \
359360
$ngx_addon_dir/src/ngx_http_lua_ssl_session_storeby.h \
360361
$ngx_addon_dir/src/ngx_http_lua_ssl_session_fetchby.h \
361362
$ngx_addon_dir/src/ngx_http_lua_ssl.h \
363+
$ngx_addon_dir/src/ngx_http_lua_proxy_ssl_verifyby.h \
362364
$ngx_addon_dir/src/ngx_http_lua_log_ringbuf.h \
363365
$ngx_addon_dir/src/ngx_http_lua_input_filters.h \
364366
$ngx_addon_dir/src/ngx_http_lua_pipe.h \

doc/HttpLuaModule.wiki

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2960,6 +2960,19 @@ Note though that configuring OpenSSL directly with <code>lua_ssl_conf_command</c
29602960
29612961
This directive was first introduced in the <code>v0.10.21</code> release.
29622962
2963+
== lua_upstream_skip_openssl_default_verify ==
2964+
2965+
'''syntax:''' ''lua_upstream_skip_openssl_default_verify on|off''
2966+
2967+
'''default:''' ''lua_upstream_skip_openssl_default_verify off''
2968+
2969+
'''context:''' ''location, location-if''
2970+
2971+
When using proxy_ssl_verify_by_lua directive, `lua_upstream_skip_openssl_default_verify` controls whether to skip default openssl's verify function, that means using pure Lua code to verify upstream server certificate.
2972+
2973+
This directive is turned <code>off</code> by default.
2974+
2975+
[Back to TOC](#directives)
29632976
29642977
29652978
== lua_http10_buffering ==

src/ngx_http_lua_common.h

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -131,23 +131,27 @@ typedef struct {
131131
(NGX_HTTP_LUA_FILE_TAG_LEN + 2 * MD5_DIGEST_LENGTH)
132132

133133

134-
/* must be within 16 bit */
135-
#define NGX_HTTP_LUA_CONTEXT_SET 0x0001
136-
#define NGX_HTTP_LUA_CONTEXT_REWRITE 0x0002
137-
#define NGX_HTTP_LUA_CONTEXT_ACCESS 0x0004
138-
#define NGX_HTTP_LUA_CONTEXT_CONTENT 0x0008
139-
#define NGX_HTTP_LUA_CONTEXT_LOG 0x0010
140-
#define NGX_HTTP_LUA_CONTEXT_HEADER_FILTER 0x0020
141-
#define NGX_HTTP_LUA_CONTEXT_BODY_FILTER 0x0040
142-
#define NGX_HTTP_LUA_CONTEXT_TIMER 0x0080
143-
#define NGX_HTTP_LUA_CONTEXT_INIT_WORKER 0x0100
144-
#define NGX_HTTP_LUA_CONTEXT_BALANCER 0x0200
145-
#define NGX_HTTP_LUA_CONTEXT_SSL_CERT 0x0400
146-
#define NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE 0x0800
147-
#define NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH 0x1000
148-
#define NGX_HTTP_LUA_CONTEXT_EXIT_WORKER 0x2000
149-
#define NGX_HTTP_LUA_CONTEXT_SSL_CLIENT_HELLO 0x4000
150-
#define NGX_HTTP_LUA_CONTEXT_SERVER_REWRITE 0x8000
134+
/* must be within 32 bits */
135+
#define NGX_HTTP_LUA_CONTEXT_SET 0x00000001
136+
#define NGX_HTTP_LUA_CONTEXT_REWRITE 0x00000002
137+
#define NGX_HTTP_LUA_CONTEXT_ACCESS 0x00000004
138+
#define NGX_HTTP_LUA_CONTEXT_CONTENT 0x00000008
139+
#define NGX_HTTP_LUA_CONTEXT_LOG 0x00000010
140+
#define NGX_HTTP_LUA_CONTEXT_HEADER_FILTER 0x00000020
141+
#define NGX_HTTP_LUA_CONTEXT_BODY_FILTER 0x00000040
142+
#define NGX_HTTP_LUA_CONTEXT_TIMER 0x00000080
143+
#define NGX_HTTP_LUA_CONTEXT_INIT_WORKER 0x00000100
144+
#define NGX_HTTP_LUA_CONTEXT_BALANCER 0x00000200
145+
#define NGX_HTTP_LUA_CONTEXT_SSL_CERT 0x00000400
146+
#define NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE 0x00000800
147+
#define NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH 0x00001000
148+
#define NGX_HTTP_LUA_CONTEXT_EXIT_WORKER 0x00002000
149+
#define NGX_HTTP_LUA_CONTEXT_SSL_CLIENT_HELLO 0x00004000
150+
#define NGX_HTTP_LUA_CONTEXT_SERVER_REWRITE 0x00008000
151+
152+
#ifdef HAVE_PROXY_SSL_PATCH
153+
#define NGX_HTTP_LUA_CONTEXT_PROXY_SSL_VERIFY 0x00010000
154+
#endif
151155

152156

153157
#define NGX_HTTP_LUA_FFI_NO_REQ_CTX -100
@@ -171,6 +175,8 @@ typedef struct ngx_http_lua_srv_conf_s ngx_http_lua_srv_conf_t;
171175

172176
typedef struct ngx_http_lua_main_conf_s ngx_http_lua_main_conf_t;
173177

178+
typedef struct ngx_http_lua_loc_conf_s ngx_http_lua_loc_conf_t;
179+
174180
typedef struct ngx_http_lua_header_val_s ngx_http_lua_header_val_t;
175181

176182
typedef struct ngx_http_lua_posted_thread_s ngx_http_lua_posted_thread_t;
@@ -184,6 +190,9 @@ typedef ngx_int_t (*ngx_http_lua_main_conf_handler_pt)(ngx_log_t *log,
184190
typedef ngx_int_t (*ngx_http_lua_srv_conf_handler_pt)(ngx_http_request_t *r,
185191
ngx_http_lua_srv_conf_t *lscf, lua_State *L);
186192

193+
typedef ngx_int_t (*ngx_http_lua_loc_conf_handler_pt)(ngx_http_request_t *r,
194+
ngx_http_lua_loc_conf_t *llcf, lua_State *L);
195+
187196
typedef ngx_int_t (*ngx_http_lua_set_header_pt)(ngx_http_request_t *r,
188197
ngx_http_lua_header_val_t *hv, ngx_str_t *value);
189198

@@ -369,7 +378,7 @@ struct ngx_http_lua_srv_conf_s {
369378
};
370379

371380

372-
typedef struct {
381+
struct ngx_http_lua_loc_conf_s {
373382
#if (NGX_HTTP_SSL)
374383
ngx_ssl_t *ssl; /* shared by SSL cosockets */
375384
ngx_array_t *ssl_certificates;
@@ -383,6 +392,16 @@ typedef struct {
383392
#if (nginx_version >= 1019004)
384393
ngx_array_t *ssl_conf_commands;
385394
#endif
395+
396+
#ifdef HAVE_PROXY_SSL_PATCH
397+
ngx_http_lua_loc_conf_handler_pt proxy_ssl_verify_handler;
398+
ngx_str_t proxy_ssl_verify_src;
399+
u_char *proxy_ssl_verify_src_key;
400+
u_char *proxy_ssl_verify_chunkname;
401+
int proxy_ssl_verify_src_ref;
402+
ngx_flag_t upstream_skip_openssl_default_verify;
403+
#endif
404+
386405
#endif
387406

388407
ngx_flag_t force_read_body; /* whether force request body to
@@ -464,7 +483,7 @@ typedef struct {
464483
ngx_flag_t log_socket_errors;
465484
ngx_flag_t check_client_abort;
466485
ngx_flag_t use_default_type;
467-
} ngx_http_lua_loc_conf_t;
486+
};
468487

469488

470489
typedef enum {
@@ -628,7 +647,7 @@ typedef struct ngx_http_lua_ctx_s {
628647

629648
int uthreads; /* number of active user threads */
630649

631-
uint16_t context; /* the current running directive context
650+
uint32_t context; /* the current running directive context
632651
(or running phase) for the current
633652
Lua chunk */
634653

src/ngx_http_lua_control.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,9 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err,
384384
| NGX_HTTP_LUA_CONTEXT_TIMER
385385
| NGX_HTTP_LUA_CONTEXT_HEADER_FILTER
386386
| NGX_HTTP_LUA_CONTEXT_BALANCER
387+
#ifdef HAVE_PROXY_SSL_PATCH
388+
| NGX_HTTP_LUA_CONTEXT_PROXY_SSL_VERIFY
389+
#endif
387390
| NGX_HTTP_LUA_CONTEXT_SSL_CLIENT_HELLO
388391
| NGX_HTTP_LUA_CONTEXT_SSL_CERT
389392
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE
@@ -395,6 +398,9 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err,
395398
}
396399

397400
if (ctx->context & (NGX_HTTP_LUA_CONTEXT_SSL_CERT
401+
#ifdef HAVE_PROXY_SSL_PATCH
402+
| NGX_HTTP_LUA_CONTEXT_PROXY_SSL_VERIFY
403+
#endif
398404
| NGX_HTTP_LUA_CONTEXT_SSL_CLIENT_HELLO
399405
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE
400406
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH))

src/ngx_http_lua_module.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131
#include "ngx_http_lua_ssl_certby.h"
3232
#include "ngx_http_lua_ssl_session_storeby.h"
3333
#include "ngx_http_lua_ssl_session_fetchby.h"
34+
35+
#ifdef HAVE_PROXY_SSL_PATCH
36+
#include "ngx_http_lua_proxy_ssl_verifyby.h"
37+
#endif
38+
3439
#include "ngx_http_lua_headers.h"
3540
#include "ngx_http_lua_headers_out.h"
3641
#if !(NGX_WIN32)
@@ -660,6 +665,30 @@ static ngx_command_t ngx_http_lua_cmds[] = {
660665
0,
661666
(void *) ngx_http_lua_ssl_sess_fetch_handler_file },
662667

668+
#ifdef HAVE_PROXY_SSL_PATCH
669+
/* same context as proxy_pass directive */
670+
{ ngx_string("proxy_ssl_verify_by_lua_block"),
671+
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
672+
ngx_http_lua_proxy_ssl_verify_by_lua_block,
673+
NGX_HTTP_LOC_CONF_OFFSET,
674+
0,
675+
(void *) ngx_http_lua_proxy_ssl_verify_handler_inline },
676+
677+
{ ngx_string("proxy_ssl_verify_by_lua_file"),
678+
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
679+
ngx_http_lua_proxy_ssl_verify_by_lua,
680+
NGX_HTTP_LOC_CONF_OFFSET,
681+
0,
682+
(void *) ngx_http_lua_proxy_ssl_verify_handler_file },
683+
684+
{ ngx_string("lua_upstream_skip_openssl_default_verify"),
685+
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_FLAG,
686+
ngx_conf_set_flag_slot,
687+
NGX_HTTP_LOC_CONF_OFFSET,
688+
offsetof(ngx_http_lua_loc_conf_t, upstream_skip_openssl_default_verify),
689+
NULL },
690+
#endif
691+
663692
{ ngx_string("lua_ssl_verify_depth"),
664693
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
665694
ngx_conf_set_num_slot,
@@ -1446,6 +1475,11 @@ ngx_http_lua_create_loc_conf(ngx_conf_t *cf)
14461475
* conf->ssl_trusted_certificate = { 0, NULL };
14471476
* conf->ssl_crl = { 0, NULL };
14481477
* conf->ssl_key_log = { 0, NULL };
1478+
*
1479+
* conf->proxy_ssl_verify_handler = NULL;
1480+
* conf->proxy_ssl_verify_src = { 0, NULL };
1481+
* conf->proxy_ssl_verify_chunkname = NULL;
1482+
* conf->proxy_ssl_verify_src_key = NULL;
14491483
*/
14501484

14511485
conf->force_read_body = NGX_CONF_UNSET;
@@ -1479,6 +1513,10 @@ ngx_http_lua_create_loc_conf(ngx_conf_t *cf)
14791513
#if (nginx_version >= 1019004)
14801514
conf->ssl_conf_commands = NGX_CONF_UNSET_PTR;
14811515
#endif
1516+
#ifdef HAVE_PROXY_SSL_PATCH
1517+
conf->proxy_ssl_verify_src_ref = LUA_REFNIL;
1518+
conf->upstream_skip_openssl_default_verify = NGX_CONF_UNSET;
1519+
#endif
14821520
#endif
14831521

14841522
return conf;
@@ -1573,6 +1611,25 @@ ngx_http_lua_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
15731611
NULL);
15741612
#endif
15751613

1614+
#ifdef HAVE_PROXY_SSL_PATCH
1615+
if (conf->proxy_ssl_verify_src.len == 0) {
1616+
conf->proxy_ssl_verify_src = prev->proxy_ssl_verify_src;
1617+
conf->proxy_ssl_verify_handler = prev->proxy_ssl_verify_handler;
1618+
conf->proxy_ssl_verify_src_ref = prev->proxy_ssl_verify_src_ref;
1619+
conf->proxy_ssl_verify_src_key = prev->proxy_ssl_verify_src_key;
1620+
conf->proxy_ssl_verify_chunkname = prev->proxy_ssl_verify_chunkname;
1621+
}
1622+
1623+
if (conf->proxy_ssl_verify_src.len) {
1624+
if (ngx_http_lua_proxy_ssl_verify_set_callback(cf) != NGX_OK) {
1625+
return NGX_CONF_ERROR;
1626+
}
1627+
}
1628+
1629+
ngx_conf_merge_value(conf->upstream_skip_openssl_default_verify,
1630+
prev->upstream_skip_openssl_default_verify, 0);
1631+
#endif
1632+
15761633
if (ngx_http_lua_set_ssl(cf, conf) != NGX_OK) {
15771634
return NGX_CONF_ERROR;
15781635
}

0 commit comments

Comments
 (0)