mirror of
https://github.com/nginx/nginx.git
synced 2024-12-22 15:13:28 -06:00
Stream ssl_preread: $ssl_preread_alpn_protocols variable.
The variable keeps a comma-separated list of protocol names from ALPN TLS extension defined by RFC 7301.
This commit is contained in:
parent
84d1e7de0c
commit
1a5604bedd
@ -17,10 +17,12 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
size_t left;
|
size_t left;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
size_t ext;
|
||||||
u_char *pos;
|
u_char *pos;
|
||||||
u_char *dst;
|
u_char *dst;
|
||||||
u_char buf[4];
|
u_char buf[4];
|
||||||
ngx_str_t host;
|
ngx_str_t host;
|
||||||
|
ngx_str_t alpn;
|
||||||
ngx_log_t *log;
|
ngx_log_t *log;
|
||||||
ngx_pool_t *pool;
|
ngx_pool_t *pool;
|
||||||
ngx_uint_t state;
|
ngx_uint_t state;
|
||||||
@ -32,6 +34,8 @@ static ngx_int_t ngx_stream_ssl_preread_parse_record(
|
|||||||
ngx_stream_ssl_preread_ctx_t *ctx, u_char *pos, u_char *last);
|
ngx_stream_ssl_preread_ctx_t *ctx, u_char *pos, u_char *last);
|
||||||
static ngx_int_t ngx_stream_ssl_preread_server_name_variable(
|
static ngx_int_t ngx_stream_ssl_preread_server_name_variable(
|
||||||
ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data);
|
ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data);
|
||||||
|
static ngx_int_t ngx_stream_ssl_preread_alpn_protocols_variable(
|
||||||
|
ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data);
|
||||||
static ngx_int_t ngx_stream_ssl_preread_add_variables(ngx_conf_t *cf);
|
static ngx_int_t ngx_stream_ssl_preread_add_variables(ngx_conf_t *cf);
|
||||||
static void *ngx_stream_ssl_preread_create_srv_conf(ngx_conf_t *cf);
|
static void *ngx_stream_ssl_preread_create_srv_conf(ngx_conf_t *cf);
|
||||||
static char *ngx_stream_ssl_preread_merge_srv_conf(ngx_conf_t *cf, void *parent,
|
static char *ngx_stream_ssl_preread_merge_srv_conf(ngx_conf_t *cf, void *parent,
|
||||||
@ -85,6 +89,9 @@ static ngx_stream_variable_t ngx_stream_ssl_preread_vars[] = {
|
|||||||
{ ngx_string("ssl_preread_server_name"), NULL,
|
{ ngx_string("ssl_preread_server_name"), NULL,
|
||||||
ngx_stream_ssl_preread_server_name_variable, 0, 0, 0 },
|
ngx_stream_ssl_preread_server_name_variable, 0, 0, 0 },
|
||||||
|
|
||||||
|
{ ngx_string("ssl_preread_alpn_protocols"), NULL,
|
||||||
|
ngx_stream_ssl_preread_alpn_protocols_variable, 0, 0, 0 },
|
||||||
|
|
||||||
ngx_stream_null_variable
|
ngx_stream_null_variable
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -139,12 +146,14 @@ ngx_stream_ssl_preread_handler(ngx_stream_session_t *s)
|
|||||||
if (p[0] != 0x16) {
|
if (p[0] != 0x16) {
|
||||||
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
||||||
"ssl preread: not a handshake");
|
"ssl preread: not a handshake");
|
||||||
|
ngx_stream_set_ctx(s, NULL, ngx_stream_ssl_preread_module);
|
||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p[1] != 3) {
|
if (p[1] != 3) {
|
||||||
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
||||||
"ssl preread: unsupported SSL version");
|
"ssl preread: unsupported SSL version");
|
||||||
|
ngx_stream_set_ctx(s, NULL, ngx_stream_ssl_preread_module);
|
||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,6 +167,12 @@ ngx_stream_ssl_preread_handler(ngx_stream_session_t *s)
|
|||||||
p += 5;
|
p += 5;
|
||||||
|
|
||||||
rc = ngx_stream_ssl_preread_parse_record(ctx, p, p + len);
|
rc = ngx_stream_ssl_preread_parse_record(ctx, p, p + len);
|
||||||
|
|
||||||
|
if (rc == NGX_DECLINED) {
|
||||||
|
ngx_stream_set_ctx(s, NULL, ngx_stream_ssl_preread_module);
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
if (rc != NGX_AGAIN) {
|
if (rc != NGX_AGAIN) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -175,7 +190,7 @@ static ngx_int_t
|
|||||||
ngx_stream_ssl_preread_parse_record(ngx_stream_ssl_preread_ctx_t *ctx,
|
ngx_stream_ssl_preread_parse_record(ngx_stream_ssl_preread_ctx_t *ctx,
|
||||||
u_char *pos, u_char *last)
|
u_char *pos, u_char *last)
|
||||||
{
|
{
|
||||||
size_t left, n, size;
|
size_t left, n, size, ext;
|
||||||
u_char *dst, *p;
|
u_char *dst, *p;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -192,7 +207,10 @@ ngx_stream_ssl_preread_parse_record(ngx_stream_ssl_preread_ctx_t *ctx,
|
|||||||
sw_ext_header, /* extension_type, extension_data length */
|
sw_ext_header, /* extension_type, extension_data length */
|
||||||
sw_sni_len, /* SNI length */
|
sw_sni_len, /* SNI length */
|
||||||
sw_sni_host_head, /* SNI name_type, host_name length */
|
sw_sni_host_head, /* SNI name_type, host_name length */
|
||||||
sw_sni_host /* SNI host_name */
|
sw_sni_host, /* SNI host_name */
|
||||||
|
sw_alpn_len, /* ALPN length */
|
||||||
|
sw_alpn_proto_len, /* ALPN protocol_name length */
|
||||||
|
sw_alpn_proto_data /* ALPN protocol_name */
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
||||||
@ -201,6 +219,7 @@ ngx_stream_ssl_preread_parse_record(ngx_stream_ssl_preread_ctx_t *ctx,
|
|||||||
state = ctx->state;
|
state = ctx->state;
|
||||||
size = ctx->size;
|
size = ctx->size;
|
||||||
left = ctx->left;
|
left = ctx->left;
|
||||||
|
ext = ctx->ext;
|
||||||
dst = ctx->dst;
|
dst = ctx->dst;
|
||||||
p = ctx->buf;
|
p = ctx->buf;
|
||||||
|
|
||||||
@ -299,10 +318,18 @@ ngx_stream_ssl_preread_parse_record(ngx_stream_ssl_preread_ctx_t *ctx,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case sw_ext_header:
|
case sw_ext_header:
|
||||||
if (p[0] == 0 && p[1] == 0) {
|
if (p[0] == 0 && p[1] == 0 && ctx->host.data == NULL) {
|
||||||
/* SNI extension */
|
/* SNI extension */
|
||||||
state = sw_sni_len;
|
state = sw_sni_len;
|
||||||
dst = NULL;
|
dst = p;
|
||||||
|
size = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p[0] == 0 && p[1] == 16 && ctx->alpn.data == NULL) {
|
||||||
|
/* ALPN extension */
|
||||||
|
state = sw_alpn_len;
|
||||||
|
dst = p;
|
||||||
size = 2;
|
size = 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -313,6 +340,7 @@ ngx_stream_ssl_preread_parse_record(ngx_stream_ssl_preread_ctx_t *ctx,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case sw_sni_len:
|
case sw_sni_len:
|
||||||
|
ext = (p[0] << 8) + p[1];
|
||||||
state = sw_sni_host_head;
|
state = sw_sni_host_head;
|
||||||
dst = p;
|
dst = p;
|
||||||
size = 3;
|
size = 3;
|
||||||
@ -325,14 +353,21 @@ ngx_stream_ssl_preread_parse_record(ngx_stream_ssl_preread_ctx_t *ctx,
|
|||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
state = sw_sni_host;
|
|
||||||
size = (p[1] << 8) + p[2];
|
size = (p[1] << 8) + p[2];
|
||||||
|
|
||||||
|
if (ext < 3 + size) {
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
||||||
|
"ssl preread: SNI format error");
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
ext -= 3 + size;
|
||||||
|
|
||||||
ctx->host.data = ngx_pnalloc(ctx->pool, size);
|
ctx->host.data = ngx_pnalloc(ctx->pool, size);
|
||||||
if (ctx->host.data == NULL) {
|
if (ctx->host.data == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state = sw_sni_host;
|
||||||
dst = ctx->host.data;
|
dst = ctx->host.data;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -341,7 +376,64 @@ ngx_stream_ssl_preread_parse_record(ngx_stream_ssl_preread_ctx_t *ctx,
|
|||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
||||||
"ssl preread: SNI hostname \"%V\"", &ctx->host);
|
"ssl preread: SNI hostname \"%V\"", &ctx->host);
|
||||||
return NGX_OK;
|
|
||||||
|
state = sw_ext;
|
||||||
|
dst = NULL;
|
||||||
|
size = ext;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sw_alpn_len:
|
||||||
|
ext = (p[0] << 8) + p[1];
|
||||||
|
|
||||||
|
ctx->alpn.data = ngx_pnalloc(ctx->pool, ext);
|
||||||
|
if (ctx->alpn.data == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = sw_alpn_proto_len;
|
||||||
|
dst = p;
|
||||||
|
size = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sw_alpn_proto_len:
|
||||||
|
size = p[0];
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
||||||
|
"ssl preread: ALPN empty protocol");
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ext < 1 + size) {
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
||||||
|
"ssl preread: ALPN format error");
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
ext -= 1 + size;
|
||||||
|
|
||||||
|
state = sw_alpn_proto_data;
|
||||||
|
dst = ctx->alpn.data + ctx->alpn.len;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sw_alpn_proto_data:
|
||||||
|
ctx->alpn.len += p[0];
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
||||||
|
"ssl preread: ALPN protocols \"%V\"", &ctx->alpn);
|
||||||
|
|
||||||
|
if (ext) {
|
||||||
|
ctx->alpn.data[ctx->alpn.len++] = ',';
|
||||||
|
|
||||||
|
state = sw_alpn_proto_len;
|
||||||
|
dst = p;
|
||||||
|
size = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = sw_ext;
|
||||||
|
dst = NULL;
|
||||||
|
size = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left < size) {
|
if (left < size) {
|
||||||
@ -354,6 +446,7 @@ ngx_stream_ssl_preread_parse_record(ngx_stream_ssl_preread_ctx_t *ctx,
|
|||||||
ctx->state = state;
|
ctx->state = state;
|
||||||
ctx->size = size;
|
ctx->size = size;
|
||||||
ctx->left = left;
|
ctx->left = left;
|
||||||
|
ctx->ext = ext;
|
||||||
ctx->dst = dst;
|
ctx->dst = dst;
|
||||||
|
|
||||||
return NGX_AGAIN;
|
return NGX_AGAIN;
|
||||||
@ -383,6 +476,29 @@ ngx_stream_ssl_preread_server_name_variable(ngx_stream_session_t *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_ssl_preread_alpn_protocols_variable(ngx_stream_session_t *s,
|
||||||
|
ngx_variable_value_t *v, uintptr_t data)
|
||||||
|
{
|
||||||
|
ngx_stream_ssl_preread_ctx_t *ctx;
|
||||||
|
|
||||||
|
ctx = ngx_stream_get_module_ctx(s, ngx_stream_ssl_preread_module);
|
||||||
|
|
||||||
|
if (ctx == NULL) {
|
||||||
|
v->not_found = 1;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
v->valid = 1;
|
||||||
|
v->no_cacheable = 0;
|
||||||
|
v->not_found = 0;
|
||||||
|
v->len = ctx->alpn.len;
|
||||||
|
v->data = ctx->alpn.data;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_ssl_preread_add_variables(ngx_conf_t *cf)
|
ngx_stream_ssl_preread_add_variables(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user