From 88b79517ac83d19cae617c6900f234250b0a8d81 Mon Sep 17 00:00:00 2001 From: Emmanuel Mathi-Amorim Date: Sun, 27 Feb 2022 21:44:57 -0500 Subject: [PATCH 1/5] Initial support for SSL in the rtmp relay module --- ngx_rtmp.h | 1 + ngx_rtmp_init.c | 9 + ngx_rtmp_relay_module.c | 459 ++++++++++++++++++++++++++++++++++++++-- ngx_rtmp_relay_module.h | 46 ++++ 4 files changed, 500 insertions(+), 15 deletions(-) diff --git a/ngx_rtmp.h b/ngx_rtmp.h index f3a3d6f18..21b6dcbdb 100644 --- a/ngx_rtmp.h +++ b/ngx_rtmp.h @@ -365,6 +365,7 @@ typedef struct { } ngx_rtmp_module_t; #define NGX_RTMP_MODULE 0x504D5452 /* "RTMP" */ +#define NGX_RTMP_SSL NGX_OPENSSL #define NGX_RTMP_MAIN_CONF 0x02000000 #define NGX_RTMP_SRV_CONF 0x04000000 diff --git a/ngx_rtmp_init.c b/ngx_rtmp_init.c index 9da711ab7..59e89ae2c 100644 --- a/ngx_rtmp_init.c +++ b/ngx_rtmp_init.c @@ -257,6 +257,15 @@ ngx_rtmp_close_connection(ngx_connection_t *c) ngx_log_debug0(NGX_LOG_DEBUG_RTMP, c->log, 0, "close connection"); +#if (NGX_RTMP_SSL) + + if (c->ssl) { + c->ssl->no_wait_shutdown = 1; + (void) ngx_ssl_shutdown(c); + } + +#endif + #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_active, -1); #endif diff --git a/ngx_rtmp_relay_module.c b/ngx_rtmp_relay_module.c index e38a3699b..eceddf6bc 100644 --- a/ngx_rtmp_relay_module.c +++ b/ngx_rtmp_relay_module.c @@ -30,6 +30,21 @@ static ngx_rtmp_relay_ctx_t * ngx_rtmp_relay_create_connection( ngx_rtmp_conf_ctx_t *cctx, ngx_str_t* name, ngx_rtmp_relay_target_t *target); +#if (NGX_RTMP_SSL) + +static void ngx_rtmp_ssl_init_connection(ngx_rtmp_session_t *rs, + ngx_rtmp_relay_target_t *target); +static void ngx_rtmp_ssl_handshake_handler(ngx_connection_t *c); +static void ngx_rtmp_ssl_handshake(ngx_rtmp_session_t *rs); +static ngx_int_t ngx_rtmp_ssl_name(ngx_rtmp_session_t *rs, + ngx_rtmp_relay_target_t *target); +static ngx_int_t ngx_rtmp_configure_ssl_name(ngx_pool_t *pool, + ngx_str_t url, ngx_str_t *ssl_name); +static ngx_int_t ngx_rtmp_configure_ssl(ngx_conf_t *cf, + ngx_rtmp_relay_app_conf_t *racf, ngx_rtmp_relay_target_t *target); + +#endif + /* _____ * =push= | |---publish---> @@ -45,21 +60,6 @@ static ngx_rtmp_relay_ctx_t * ngx_rtmp_relay_create_connection( */ -typedef struct { - ngx_array_t pulls; /* ngx_rtmp_relay_target_t * */ - ngx_array_t pushes; /* ngx_rtmp_relay_target_t * */ - ngx_array_t static_pulls; /* ngx_rtmp_relay_target_t * */ - ngx_array_t static_events; /* ngx_event_t * */ - ngx_log_t *log; - ngx_uint_t nbuckets; - ngx_msec_t buflen; - ngx_flag_t session_relay; - ngx_msec_t push_reconnect; - ngx_msec_t pull_reconnect; - ngx_rtmp_relay_ctx_t **ctx; -} ngx_rtmp_relay_app_conf_t; - - typedef struct { ngx_rtmp_conf_ctx_t cctx; ngx_rtmp_relay_target_t *target; @@ -79,6 +79,21 @@ typedef struct { #define NGX_RTMP_RELAY_FLASHVER "LNX.11,1,102,55" +#if (NGX_RTMP_SSL) + +static ngx_conf_bitmask_t ngx_rtmp_relay_ssl_protocols[] = { + { ngx_string("SSLv2"), NGX_SSL_SSLv2 }, + { ngx_string("SSLv3"), NGX_SSL_SSLv3 }, + { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, + { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, + { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, + { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 }, + { ngx_null_string, 0 } +}; + +#endif + + static ngx_command_t ngx_rtmp_relay_commands[] = { { ngx_string("push"), @@ -123,6 +138,58 @@ static ngx_command_t ngx_rtmp_relay_commands[] = { offsetof(ngx_rtmp_relay_app_conf_t, session_relay), NULL }, +#if (NGX_RTMP_SSL) + + { ngx_string("rtmp_relay_ssl_protocols"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, + ngx_conf_set_bitmask_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_relay_app_conf_t, ssl_protocols), + &ngx_rtmp_relay_ssl_protocols }, + + { ngx_string("rtmp_relay_ssl_ciphers"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_relay_app_conf_t, ssl_ciphers), + NULL }, + + { ngx_string("rtmp_relay_ssl_server_name"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_relay_app_conf_t, ssl_server_name), + NULL }, + + { ngx_string("rtmp_relay_ssl_verify"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_relay_app_conf_t, ssl_verify), + NULL }, + + { ngx_string("rtmp_relay_ssl_verify_depth"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_relay_app_conf_t, ssl_verify_depth), + NULL }, + + { ngx_string("rtmp_relay_ssl_trusted_certificate"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_relay_app_conf_t, ssl_trusted_certificate), + NULL }, + + { ngx_string("rtmp_relay_ssl_crl"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_relay_app_conf_t, ssl_crl), + NULL }, + +#endif ngx_null_command }; @@ -193,6 +260,23 @@ ngx_rtmp_relay_create_app_conf(ngx_conf_t *cf) racf->push_reconnect = NGX_CONF_UNSET_MSEC; racf->pull_reconnect = NGX_CONF_UNSET_MSEC; +#if (NGX_RTMP_SSL) + + /* + * the following are automatically zeroed out by pcalloc + * + * racf->ssl_protocols + * racf->ssl_ciphers + * racf->ssl_trusted_certificate + * racf->ssl_crl + */ + + racf->ssl_server_name = NGX_CONF_UNSET; + racf->ssl_verify = NGX_CONF_UNSET; + racf->ssl_verify_depth = NGX_CONF_UNSET_UINT; + +#endif + return racf; } @@ -213,6 +297,41 @@ ngx_rtmp_relay_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_msec_value(conf->pull_reconnect, prev->pull_reconnect, 3000); +#if (NGX_RTMP_SSL) + + ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols, + (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 + |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); + ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); + ngx_conf_merge_value(conf->ssl_server_name, prev->ssl_server_name, 1); + ngx_conf_merge_value(conf->ssl_verify, prev->ssl_verify, 1); + ngx_conf_merge_uint_value(conf->ssl_verify_depth, prev->ssl_verify_depth, + 1); + ngx_conf_merge_str_value(conf->ssl_trusted_certificate, + prev->ssl_trusted_certificate, ""); + ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); + +#define ngx_rtmp_configure_ssl_for_arr(arr) \ + { \ + ngx_uint_t i; \ + ngx_rtmp_relay_target_t *target; \ + for (i = 0; i < (arr).nelts; i++) { \ + target = *((ngx_rtmp_relay_target_t **)((arr).elts) + i); \ + if (ngx_rtmp_configure_ssl(cf, conf, target) \ + != NGX_OK) { \ + return NGX_CONF_ERROR; \ + } \ + } \ + } + + ngx_rtmp_configure_ssl_for_arr(conf->pulls); + ngx_rtmp_configure_ssl_for_arr(conf->pushes); + ngx_rtmp_configure_ssl_for_arr(conf->static_pulls); + +#undef ngx_rtmp_configure_ssl_for_arr + +#endif + return NGX_CONF_OK; } @@ -397,6 +516,14 @@ ngx_rtmp_relay_create_connection(ngx_rtmp_conf_ctx_t *cctx, ngx_str_t* name, #undef NGX_RTMP_RELAY_STR_COPY +#if (NGX_RTMP_SSL) + + rctx->ssl_name = target->ssl_name; + rctx->ssl_server_name = target->ssl_server_name; + rctx->ssl_verify = target->ssl_verify; + +#endif + if (rctx->app.len == 0 || rctx->play_path.len == 0) { /* parse uri */ uri = &target->url.uri; @@ -507,6 +634,14 @@ ngx_rtmp_relay_create_connection(ngx_rtmp_conf_ctx_t *cctx, ngx_str_t* name, (void) ngx_atomic_fetch_add(ngx_stat_active, 1); #endif +#if (NGX_RTMP_SSL) + if (target->is_rtmps) { + c->data = rs; + ngx_rtmp_ssl_init_connection(rs, target); + return rctx; + } +#endif + ngx_rtmp_client_handshake(rs, 1); return rctx; @@ -1677,6 +1812,26 @@ ngx_rtmp_relay_push_pull(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) u->url.len -= 7; } +#if (NGX_RTMP_SSL) + + if (ngx_strncasecmp(u->url.data, (u_char *) "rtmps://", 8) == 0) { + u->url.data += 8; + u->url.len -= 8; + + u->default_port = 443; + + target->is_rtmps = 1; + target->ssl_server_name = NGX_CONF_UNSET; + target->ssl_verify = NGX_CONF_UNSET; + + if (ngx_rtmp_configure_ssl_name(cf->pool, u->url, + &target->ssl_name) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + +#endif + if (ngx_parse_url(cf->pool, u) != NGX_OK) { if (u->err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -1728,6 +1883,34 @@ ngx_rtmp_relay_push_pull(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) NGX_RTMP_RELAY_NUM_PAR("start", start); NGX_RTMP_RELAY_NUM_PAR("stop", stop); +#if (NGX_RTMP_SSL) + +#define NGX_RTMP_RELAY_FLAG_PAR(name, var) \ + if (n.len == sizeof(name) - 1 \ + && ngx_strncasecmp(n.data, (u_char *) name, n.len) == 0) \ + { \ + if (ngx_strncasecmp(v.data, (u_char *) "on", v.len) == 0) { \ + target->var = 1; \ + } else if (ngx_strncasecmp(v.data, (u_char *) "off", v.len) \ + == 0) \ + { \ + target->var = 0; \ + } else { \ + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, \ + "invalid value \"%V\" in \"%V\" directive, " \ + "it must be \"on\" or \"off\"", &v, &n); \ + return NGX_CONF_ERROR; \ + } \ + continue; \ + } + + if (target->is_rtmps) { + NGX_RTMP_RELAY_FLAG_PAR("ssl_server_name", ssl_server_name); + NGX_RTMP_RELAY_FLAG_PAR("ssl_verify", ssl_verify); + } + +#endif + #undef NGX_RTMP_RELAY_STR_PAR #undef NGX_RTMP_RELAY_NUM_PAR @@ -1897,3 +2080,249 @@ ngx_rtmp_relay_postconfiguration(ngx_conf_t *cf) return NGX_OK; } + + +#if (NGX_RTMP_SSL) + +static void +ngx_rtmp_ssl_init_connection(ngx_rtmp_session_t *rs, + ngx_rtmp_relay_target_t *target) +{ + ngx_int_t rc; + ngx_connection_t *c; + + c = rs->connection; + + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, c->log, 0, + "relay: initialize SSL connection"); + + if (ngx_ssl_create_connection(target->ssl, c, + NGX_SSL_BUFFER|NGX_SSL_CLIENT) + != NGX_OK) + { + ngx_rtmp_finalize_session(rs); + return; + } + + c->sendfile = 0; + + if (target->ssl_server_name && ngx_rtmp_ssl_name(rs, target) != NGX_OK) { + ngx_rtmp_finalize_session(rs); + return; + } + + rc = ngx_ssl_handshake(c); + + if (rc == NGX_AGAIN) { + + if (!c->write->timer_set) { + ngx_add_timer(c->write, rs->timeout); + } + + c->ssl->handler = ngx_rtmp_ssl_handshake_handler; + return; + } + + ngx_rtmp_ssl_handshake(rs); +} + + +static void +ngx_rtmp_ssl_handshake_handler(ngx_connection_t *c) +{ + ngx_rtmp_session_t *rs; + + rs = c->data; + ngx_rtmp_ssl_handshake(rs); +} + + +static void +ngx_rtmp_ssl_handshake(ngx_rtmp_session_t *rs) +{ + ngx_connection_t *c; + ngx_rtmp_relay_ctx_t *rctx; + long rc; + + c = rs->connection; + rctx = ngx_rtmp_get_module_ctx(rs, ngx_rtmp_relay_module); + + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, c->log, 0, "relay: SSL handshaking"); + + if (c->ssl->handshaked) { + if (rctx->ssl_verify && rctx->ssl_name.len != 0) { + rc = SSL_get_verify_result(c->ssl->connection); + + if (rc != X509_V_OK) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "relay: SSL certificate verify error: (%l:%s)", + rc, X509_verify_cert_error_string(rc)); + goto err; + } + + if (ngx_ssl_check_host(c, &rctx->ssl_name) != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "relay: SSL certificate does not match \"%V\"", + &rctx->ssl_name); + goto err; + } + } + + ngx_rtmp_client_handshake(rs, 1); + return; + } + + if (c->write->timedout) { + goto err; + } + +err: + ngx_rtmp_finalize_session(rs); +} + + +static ngx_int_t +ngx_rtmp_ssl_name(ngx_rtmp_session_t *rs, ngx_rtmp_relay_target_t *target) +{ + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + + ngx_connection_t *c; + + c = rs->connection; + + if (target->ssl_name.len == 0) { + return NGX_OK; + } + + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, c->log, 0, + "relay: SSL server name: \"%V\"", &target->ssl_name); + + if (SSL_set_tlsext_host_name(c->ssl->connection, target->ssl_name.data) + == 0) + { + ngx_ssl_error(NGX_LOG_ERR, c->log, 0, + "SSL_set_tlsext_host_name(\"%V\") failed", + &target->ssl_name); + return NGX_ERROR; + } + +#endif + + return NGX_OK; +} + +static ngx_int_t +ngx_rtmp_configure_ssl_name(ngx_pool_t *pool, ngx_str_t url, ngx_str_t *ssl_name) +{ + u_char *host, *port, *last, *uri, *args, *p; + + if (url.len == 0) { + goto no_ssl_name; + } + + host = url.data; + last = host + url.len; + + if (url.data[0] == '[') { + /* found a literal IPv6 address */ + goto no_ssl_name; + } + + port = ngx_strlchr(host, last, ':'); + uri = ngx_strlchr(host, last, '/'); + args = ngx_strlchr(host, last, '?'); + + /* find the end of the hostname part of the url */ + if (port) { + last = port; + } else if (uri) { + last = uri; + } else if (args) { + last = args; + } + + if (ngx_inet_addr(host, last - host) != INADDR_NONE) { + goto no_ssl_name; + } + + p = ngx_pnalloc(pool, (last - host) + 1); + if (p == NULL) { + goto err; + } + + (void) ngx_cpystrn(p, host, (last - host) + 1); + + ssl_name->len = last - host; + ssl_name->data = p; + return NGX_OK; + +no_ssl_name: + return NGX_OK; + +err: + return NGX_ERROR; +} + + +static ngx_int_t +ngx_rtmp_configure_ssl(ngx_conf_t *cf, ngx_rtmp_relay_app_conf_t *racf, + ngx_rtmp_relay_target_t *target) +{ + ngx_pool_cleanup_t *cln; + + if (target->is_rtmps) { + target->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); + if (target->ssl == NULL) { + return NGX_ERROR; + } + + target->ssl->log = cf->log; + + if (ngx_ssl_create(target->ssl, racf->ssl_protocols, NULL) != NGX_OK) { + return NGX_ERROR; + } + + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + ngx_ssl_cleanup_ctx(target->ssl); + return NGX_ERROR; + } + + cln->handler = ngx_ssl_cleanup_ctx; + cln->data = target->ssl; + + if (ngx_ssl_ciphers(cf, target->ssl, &racf->ssl_ciphers, 0) + != NGX_OK) { + return NGX_ERROR; + } + + ngx_conf_merge_value(target->ssl_server_name, + racf->ssl_server_name, 0); + ngx_conf_merge_value(target->ssl_verify, racf->ssl_verify, 0); + + if (target->ssl_verify) { + if (racf->ssl_trusted_certificate.len == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "relay: no rtmp_relay_ssl_trusted_certificate for rtmp_relay_ssl_verify"); + return NGX_ERROR; + } + + if (ngx_ssl_trusted_certificate(cf, target->ssl, + &racf->ssl_trusted_certificate, + racf->ssl_verify_depth) + != NGX_OK) + { + return NGX_ERROR; + } + + if (ngx_ssl_crl(cf, target->ssl, &racf->ssl_crl) != NGX_OK) { + return NGX_ERROR; + } + } + } + + return NGX_OK; +} + +#endif diff --git a/ngx_rtmp_relay_module.h b/ngx_rtmp_relay_module.h index d1baeae61..52da82962 100644 --- a/ngx_rtmp_relay_module.h +++ b/ngx_rtmp_relay_module.h @@ -26,6 +26,16 @@ typedef struct { ngx_int_t start; ngx_int_t stop; +#if (NGX_RTMP_SSL) + + ngx_int_t is_rtmps; + ngx_ssl_t *ssl; + ngx_str_t ssl_name; + ngx_flag_t ssl_server_name; + ngx_flag_t ssl_verify; + +#endif + void *tag; /* usually module reference */ void *data; /* module-specific data */ ngx_uint_t counter; /* mutable connection counter */ @@ -53,6 +63,14 @@ struct ngx_rtmp_relay_ctx_s { ngx_int_t start; ngx_int_t stop; +#if (NGX_RTMP_SSL) + + ngx_str_t ssl_name; + ngx_flag_t ssl_server_name; + ngx_flag_t ssl_verify; + +#endif + ngx_event_t push_evt; ngx_event_t *static_evt; void *tag; @@ -60,6 +78,34 @@ struct ngx_rtmp_relay_ctx_s { }; +typedef struct { + ngx_array_t pulls; /* ngx_rtmp_relay_target_t * */ + ngx_array_t pushes; /* ngx_rtmp_relay_target_t * */ + ngx_array_t static_pulls; /* ngx_rtmp_relay_target_t * */ + ngx_array_t static_events; /* ngx_event_t * */ + ngx_log_t *log; + ngx_uint_t nbuckets; + ngx_msec_t buflen; + ngx_flag_t session_relay; + ngx_msec_t push_reconnect; + ngx_msec_t pull_reconnect; + ngx_rtmp_relay_ctx_t **ctx; + +#if (NGX_RTMP_SSL) + + ngx_uint_t ssl_protocols; + ngx_str_t ssl_ciphers; + ngx_flag_t ssl_server_name; + ngx_flag_t ssl_verify; + ngx_uint_t ssl_verify_depth; + ngx_str_t ssl_trusted_certificate; + ngx_str_t ssl_crl; + +#endif + +} ngx_rtmp_relay_app_conf_t; + + extern ngx_module_t ngx_rtmp_relay_module; From 366218c0630fb22360d0a21b93a7dbc6ef8ae786 Mon Sep 17 00:00:00 2001 From: Emmanuel Mathi-Amorim Date: Thu, 3 Mar 2022 22:03:02 -0500 Subject: [PATCH 2/5] Add documentation for new SSL directives in the relay module --- doc/directives.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/doc/directives.md b/doc/directives.md index 9ad1f25db..b415061b6 100644 --- a/doc/directives.md +++ b/doc/directives.md @@ -69,6 +69,13 @@ Table of Contents * [push](#push) * [push_reconnect](#push_reconnect) * [session_relay](#session_relay) + * [rtmp_relay_ssl_protocols](#rtmp_relay_ssl_protocols) + * [rtmp_relay_ssl_ciphers](#rtmp_relay_ssl_ciphers) + * [rtmp_relay_ssl_server_name](#rtmp_relay_ssl_server_name) + * [rtmp_relay_ssl_verify](#rtmp_relay_ssl_verify) + * [rtmp_relay_ssl_verify_depth](#rtmp_relay_ssl_verify_depth) + * [rtmp_relay_ssl_trusted_certificate](#rtmp_relay_ssl_trusted_certificate) + * [rtmp_relay_ssl_crl](#rtmp_relay_ssl_crl) * [Notify](#notify) * [on_connect](#on_connect) * [on_play](#on_play) @@ -913,6 +920,8 @@ all local streams within application are pulled * start - start time in seconds * stop - stop time in seconds * static - makes pull static, such pull is created at nginx start +* ssl_server_name - overrides rtmp_relay_ssl_server_name directive, values: on, off +* ssl_verify - overrides rtmp_relay_ssl_verify directive, values: on, off If a value for a parameter contains spaces then you should use quotes around the **WHOLE** key=value pair like this : `'pageUrl=FAKE PAGE URL'`. @@ -950,6 +959,71 @@ could possibly be created later. Default is off. session_relay on; ``` +#### rtmp_relay_ssl_protocols +Syntax: `rtmp_relay_ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3];` +Context: rtmp, server, application + +Enables the specified protocols for streams pushed/pulled to/from the RTMPS server. Default is TLSv1 TLSv1.1 TLSv1.2. +```sh +rtmp_relay_ssl_protocols TLSv1.2 TLSv1.3; +``` + +#### rtmp_relay_ssl_ciphers +Syntax: `rtmp_relay_ssl_ciphers ciphers;` +Context: rtmp, server, application + +Specifies the enabled ciphers for for streams pushed/pulled to/from the RTMPS server. The ciphers are specified in the format understood by the OpenSSL library. Default is openssl `DEFAULT`. + +The full list can be viewed using the `openssl ciphers` command. +```sh +rtmp_relay_ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; +``` + +#### rtmp_relay_ssl_server_name +Syntax: `rtmp_relay_ssl_server_name on | off;` +Context: rtmp, server, application + +Enables or disables passing of the server name through TLS Server Name Indication extension (SNI, RFC 6066) when establishing a connection with the RTMPS server. Default is on. +```sh +rtmp_relay_ssl_server_name on; +``` + +#### rtmp_relay_ssl_verify +Syntax: `rtmp_relay_ssl_verify on | off;` +Context: rtmp, server, application + +Enables or disables verification of the RTMPS server certificate. Note you must set the rtmp_relay_ssl_trusted_certificate. Default is on. +```sh +rtmp_relay_ssl_verify on; +``` + +#### rtmp_relay_ssl_verify_depth +Syntax: `rtmp_relay_ssl_verify_depth number;` +Context: rtmp, server, application + +Sets the verification depth in the RTMPS server certificates chain. Default is 1. +```sh +rtmp_relay_ssl_verify_depth 1; +``` + +#### rtmp_relay_ssl_trusted_certificate +Syntax: `rtmp_relay_ssl_trusted_certificate file;` +Context: rtmp, server, application + +Specifies a file with trusted CA certificates in the PEM format used to verify the certificate of the RTMPS server. No default set. +```sh +rtmp_relay_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; +``` + +#### rtmp_relay_ssl_crl +Syntax: `rtmp_relay_ssl_crl file;` +Context: rtmp, server, application + +Specifies a file with revoked certificates (CRL) in the PEM format used to verify the certificate of the RTMPS server. No default set. +```sh +rtmp_relay_ssl_crl /etc/ssl/certs/crl.crt; +``` + ## Notify #### on_connect From f07f1871c19da435c31a3287ca29e22d20b5d719 Mon Sep 17 00:00:00 2001 From: Emmanuel Mathi-Amorim Date: Thu, 10 Mar 2022 22:04:14 -0500 Subject: [PATCH 3/5] fix segfault in the relay module when initial push fails When the initial push to a target fails in the relay module we can segfault since the relay ctx is NULL. THe segfault occurs in the if which sets up the timer for the push_reconnect method. In this patch we set the context using the existing create local ctx method passing in a NULL target as the target is unused in this method. --- ngx_rtmp_relay_module.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ngx_rtmp_relay_module.c b/ngx_rtmp_relay_module.c index eceddf6bc..7ed40abef 100644 --- a/ngx_rtmp_relay_module.c +++ b/ngx_rtmp_relay_module.c @@ -812,6 +812,10 @@ ngx_rtmp_relay_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) name.len = ngx_strlen(v->name); name.data = v->name; + if (ctx == NULL) { + ctx = ngx_rtmp_relay_create_local_ctx(s, &name, NULL); + } + t = racf->pushes.elts; for (n = 0; n < racf->pushes.nelts; ++n, ++t) { target = *t; From fa7bdcfbd72503ccc5b4dbf77409053c8db61fdb Mon Sep 17 00:00:00 2001 From: Emmanuel Mathi-Amorim Date: Sun, 27 Mar 2022 09:02:34 -0400 Subject: [PATCH 4/5] Add DNS & RTMPS support for the notify module on_publish When the notify module receives a 3xx response to the on_publish callback we will now support sending the stream to an rtmps target and we will support resolving the domain name. --- ngx_rtmp.h | 2 + ngx_rtmp_core_module.c | 62 +++++++++- ngx_rtmp_notify_module.c | 238 +++++++++++++++++++++++++++++++++++++-- ngx_rtmp_relay_module.c | 19 ++-- ngx_rtmp_relay_module.h | 10 ++ 5 files changed, 309 insertions(+), 22 deletions(-) diff --git a/ngx_rtmp.h b/ngx_rtmp.h index 21b6dcbdb..e38f6e942 100644 --- a/ngx_rtmp.h +++ b/ngx_rtmp.h @@ -338,6 +338,8 @@ typedef struct ngx_rtmp_core_srv_conf_s { typedef struct { ngx_array_t applications; /* ngx_rtmp_core_app_conf_t */ ngx_str_t name; + ngx_resolver_t *resolver; + ngx_msec_t resolver_timeout; void **app_conf; } ngx_rtmp_core_app_conf_t; diff --git a/ngx_rtmp_core_module.c b/ngx_rtmp_core_module.c index 1037f823f..4f03cef64 100644 --- a/ngx_rtmp_core_module.c +++ b/ngx_rtmp_core_module.c @@ -24,6 +24,8 @@ static char *ngx_rtmp_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_rtmp_core_application(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_rtmp_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); ngx_rtmp_core_main_conf_t *ngx_rtmp_core_main_conf; @@ -157,6 +159,20 @@ static ngx_command_t ngx_rtmp_core_commands[] = { offsetof(ngx_rtmp_core_srv_conf_t, buflen), NULL }, + { ngx_string("resolver"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, + ngx_rtmp_core_resolver, + NGX_RTMP_APP_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("resolver_timeout"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_core_app_conf_t, resolver_timeout), + NULL }, + ngx_null_command }; @@ -308,6 +324,8 @@ ngx_rtmp_core_create_app_conf(ngx_conf_t *cf) return NULL; } + conf->resolver_timeout = NGX_CONF_UNSET_MSEC; + return conf; } @@ -318,8 +336,26 @@ ngx_rtmp_core_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) ngx_rtmp_core_app_conf_t *prev = parent; ngx_rtmp_core_app_conf_t *conf = child; - (void)prev; - (void)conf; + ngx_conf_merge_msec_value(conf->resolver_timeout, + prev->resolver_timeout, 30000); + + if (conf->resolver == NULL) { + + if (prev->resolver == NULL) { + + /* + * create dummy resolver in rtmp {} context + * to inherit it in all servers + */ + + prev->resolver = ngx_resolver_create(cf, NULL, 0); + if (prev->resolver == NULL) { + return NGX_CONF_ERROR; + } + } + + conf->resolver = prev->resolver; + } return NGX_CONF_OK; } @@ -743,3 +779,25 @@ ngx_rtmp_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_OK; } + + +static char * +ngx_rtmp_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_rtmp_core_app_conf_t *cacf = conf; + + ngx_str_t *value; + + if (cacf->resolver) { + return "is duplicate"; + } + + value = cf->args->elts; + + cacf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1); + if (cacf->resolver == NULL) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} diff --git a/ngx_rtmp_notify_module.c b/ngx_rtmp_notify_module.c index 04ee64a5b..806b37d11 100644 --- a/ngx_rtmp_notify_module.c +++ b/ngx_rtmp_notify_module.c @@ -41,6 +41,8 @@ static char *ngx_rtmp_notify_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child); static ngx_int_t ngx_rtmp_notify_done(ngx_rtmp_session_t *s, char *cbname, ngx_uint_t url_idx); +static void ngx_rtmp_notify_reset_relay_target( + ngx_rtmp_relay_target_t *target); ngx_str_t ngx_rtmp_notify_urlencoded = @@ -80,6 +82,7 @@ typedef struct { ngx_msec_t update_timeout; ngx_flag_t update_strict; ngx_flag_t relay_redirect; + ngx_rtmp_relay_target_t *publish_relay_target; } ngx_rtmp_notify_app_conf_t; @@ -105,6 +108,13 @@ typedef struct { } ngx_rtmp_notify_done_t; +typedef struct { + ngx_rtmp_session_t *session; + ngx_str_t name; + ngx_rtmp_relay_target_t *target; +} ngx_rtmp_notify_push_pull_ctx_t; + + static ngx_command_t ngx_rtmp_notify_commands[] = { { ngx_string("on_connect"), @@ -283,6 +293,7 @@ ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_rtmp_notify_app_conf_t *prev = parent; ngx_rtmp_notify_app_conf_t *conf = child; + ngx_rtmp_relay_app_conf_t *racf; ngx_uint_t n; for (n = 0; n < NGX_RTMP_NOTIFY_APP_MAX; ++n) { @@ -296,6 +307,29 @@ ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) prev->active = 1; } + racf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_relay_module); + + if (conf->url[NGX_RTMP_NOTIFY_PUBLISH]) { + conf->publish_relay_target = + ngx_pcalloc(cf->pool, sizeof(*(conf->publish_relay_target))); + if (conf->publish_relay_target == NULL) { + return NGX_CONF_ERROR; + } + +#if (NGX_RTMP_SSL) + conf->publish_relay_target->is_rtmps = 1; + conf->publish_relay_target->ssl_server_name = NGX_CONF_UNSET; + conf->publish_relay_target->ssl_verify = NGX_CONF_UNSET; + + if (ngx_rtmp_relay_configure_ssl(cf, racf, conf->publish_relay_target) + != NGX_OK) + { + return NGX_CONF_ERROR; + } +#endif + } + + ngx_conf_merge_uint_value(conf->method, prev->method, NGX_RTMP_NETCALL_HTTP_POST); ngx_conf_merge_value(conf->send_redirect, prev->send_redirect, 0); @@ -1312,6 +1346,123 @@ ngx_rtmp_notify_set_name(u_char *dst, size_t dst_len, u_char *src, } +static void +ngx_rtmp_notify_reset_relay_target(ngx_rtmp_relay_target_t *target) +{ +#if (NGX_RTMP_SSL) + ngx_ssl_t *ssl; + ngx_flag_t ssl_server_name; + ngx_flag_t ssl_verify; + + ssl = target->ssl; + ssl_server_name = target->ssl_server_name; + ssl_verify = target->ssl_verify; +#endif + + ngx_memzero(target, sizeof(*target)); + +#if (NGX_RTMP_SSL) + target->ssl = ssl; + target->ssl_server_name = ssl_server_name; + target->ssl_verify = ssl_verify; +#endif +} + + +static void +ngx_rtmp_notify_resolve_handler(ngx_resolver_ctx_t *ctx) +{ + ngx_rtmp_notify_push_pull_ctx_t *push_pull_ctx; + ngx_rtmp_session_t *s; + ngx_rtmp_relay_target_t *target; + ngx_uint_t naddrs, i; + ngx_resolver_addr_t *addrs; + struct sockaddr *sa; + u_char *p; + size_t len; + + + push_pull_ctx = ctx->data; + s = push_pull_ctx->session; + target = push_pull_ctx->target; + + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "rtmp notify resolve"); + + if (ctx->state) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "%V could not be resolved (%i: %s)", + &ctx->name, ctx->state, + ngx_resolver_strerror(ctx->state)); + ngx_rtmp_finalize_session(s); + return; + } + + naddrs = ctx->naddrs; + addrs = ctx->addrs; + +#if (NGX_DEBUG) + { + u_char text[NGX_SOCKADDR_STRLEN]; + ngx_str_t addr; + ngx_uint_t i; + + addr.data = text; + + for (i = 0; i < ctx->naddrs; i++) { + addr.len = ngx_sock_ntop(addrs[i].sockaddr, addrs[i].socklen, + text, NGX_SOCKADDR_STRLEN, 0); + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "name was resolved to %V", &addr); + } + } +#endif + + target->url.naddrs = naddrs; + target->url.addrs = ngx_pcalloc(s->connection->pool, + sizeof(ngx_addr_t) * naddrs); + if (target->url.addrs == NULL) { + goto error; + } + + for (i = 0; i < naddrs; i++) { + sa = ngx_pcalloc(s->connection->pool, addrs[i].socklen); + if (sa == NULL) { + goto error; + } + ngx_memcpy(sa, addrs[i].sockaddr, addrs[i].socklen); + + ngx_inet_set_port(sa, target->url.port); + target->url.addrs[i].sockaddr = sa; + target->url.addrs[i].socklen = addrs[i].socklen; + + p = ngx_pnalloc(s->connection->pool, NGX_SOCKADDR_STRLEN); + if (p == NULL) { + goto error; + } + + len = ngx_sock_ntop(sa, addrs[i].socklen, p, NGX_SOCKADDR_STRLEN, 1); + + target->url.addrs[i].name.len = len; + target->url.addrs[i].name.data = p; + } + + ngx_resolve_name_done(ctx); + + ngx_rtmp_relay_configure_ssl_name(s->connection->pool, + target->url.url, + &target->ssl_name); + ngx_rtmp_relay_push(s, &push_pull_ctx->name, target); + return; + +error: + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "error processing resolver response"); + ngx_rtmp_finalize_session(s); +} + + static ngx_int_t ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s, void *arg, ngx_chain_t *in) @@ -1319,9 +1470,12 @@ ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v = arg; ngx_int_t rc, send; ngx_str_t local_name; - ngx_rtmp_relay_target_t target; + ngx_rtmp_relay_target_t *target; ngx_url_t *u; + ngx_rtmp_core_app_conf_t *cacf; ngx_rtmp_notify_app_conf_t *nacf; + ngx_resolver_ctx_t *ctx, temp; + ngx_rtmp_notify_push_pull_ctx_t *push_pull_ctx; u_char name[NGX_RTMP_MAX_NAME]; static ngx_str_t location = ngx_string("location"); @@ -1370,7 +1524,12 @@ ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s, goto next; } - if (ngx_strncasecmp(name, (u_char *) "rtmp://", 7)) { + if ((ngx_strncasecmp(name, (u_char *) "rtmp://", 7) != 0) +#if (NGX_RTMP_SSL) + && (ngx_strncasecmp(name, (u_char *) "rtmps://", 8) != 0) +#endif + ) + { *ngx_cpymem(v->name, name, rc) = 0; ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "notify: publish redirect to '%s'", v->name); @@ -1379,6 +1538,7 @@ ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s, /* push */ + cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_core_module); nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); if (nacf->send_redirect) { @@ -1434,23 +1594,83 @@ ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s, local_name.data = v->name; local_name.len = ngx_strlen(v->name); - ngx_memzero(&target, sizeof(target)); + target = nacf->publish_relay_target; - u = &target.url; - u->url = local_name; - u->url.data = name + 7; - u->url.len = rc - 7; - u->default_port = 1935; + ngx_rtmp_notify_reset_relay_target(target); + + u = &target->url; u->uri_part = 1; u->no_resolve = 1; /* want ip here */ +#if (NGX_RTMP_SSL) + if (ngx_strncasecmp(name, (u_char *) "rtmps://", 8) == 0) { + u->url.data = name + 8; + u->url.len = rc - 8; + u->default_port = 443; + + target->is_rtmps = 1; + } else +#endif + { + u->url.data = name + 7; + u->url.len = rc - 7; + u->default_port = 1935; + + target->is_rtmps = 0; + } + + u->url.data = ngx_pstrdup(s->connection->pool, &u->url); + if (u->url.data == NULL) { + return NGX_ERROR; + } + if (ngx_parse_url(s->connection->pool, u) != NGX_OK) { ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "notify: push failed '%V'", &local_name); return NGX_ERROR; } - ngx_rtmp_relay_push(s, &local_name, &target); + if (u->naddrs == 0) { + /* need to resolve the name */ + temp.name = u->host; + ctx = ngx_resolve_start(cacf->resolver, &temp); + if (ctx == NULL) { + return NGX_ERROR; + } + + if (ctx == NGX_NO_RESOLVER) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "no resolver defined to resolve %V", &u->host); + return NGX_ERROR; + } + + push_pull_ctx = ngx_pcalloc(s->connection->pool, + sizeof(*push_pull_ctx)); + if (push_pull_ctx == NULL) { + return NGX_ERROR; + } + + push_pull_ctx->session = s; + push_pull_ctx->name.data = ngx_pstrdup(s->connection->pool, + &local_name); + push_pull_ctx->name.len = local_name.len; + push_pull_ctx->target = target; + + if (push_pull_ctx->name.data == NULL) { + return NGX_ERROR; + } + + ctx->name = u->host; + ctx->handler = ngx_rtmp_notify_resolve_handler; + ctx->data = push_pull_ctx; + ctx->timeout = cacf->resolver_timeout; + + if (ngx_resolve_name(ctx) != NGX_OK) { + return NGX_ERROR; + } + } else { + ngx_rtmp_relay_push(s, &local_name, target); + } next: diff --git a/ngx_rtmp_relay_module.c b/ngx_rtmp_relay_module.c index 7ed40abef..1ad488d8f 100644 --- a/ngx_rtmp_relay_module.c +++ b/ngx_rtmp_relay_module.c @@ -38,10 +38,6 @@ static void ngx_rtmp_ssl_handshake_handler(ngx_connection_t *c); static void ngx_rtmp_ssl_handshake(ngx_rtmp_session_t *rs); static ngx_int_t ngx_rtmp_ssl_name(ngx_rtmp_session_t *rs, ngx_rtmp_relay_target_t *target); -static ngx_int_t ngx_rtmp_configure_ssl_name(ngx_pool_t *pool, - ngx_str_t url, ngx_str_t *ssl_name); -static ngx_int_t ngx_rtmp_configure_ssl(ngx_conf_t *cf, - ngx_rtmp_relay_app_conf_t *racf, ngx_rtmp_relay_target_t *target); #endif @@ -317,7 +313,7 @@ ngx_rtmp_relay_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) ngx_rtmp_relay_target_t *target; \ for (i = 0; i < (arr).nelts; i++) { \ target = *((ngx_rtmp_relay_target_t **)((arr).elts) + i); \ - if (ngx_rtmp_configure_ssl(cf, conf, target) \ + if (ngx_rtmp_relay_configure_ssl(cf, conf, target) \ != NGX_OK) { \ return NGX_CONF_ERROR; \ } \ @@ -1828,8 +1824,8 @@ ngx_rtmp_relay_push_pull(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) target->ssl_server_name = NGX_CONF_UNSET; target->ssl_verify = NGX_CONF_UNSET; - if (ngx_rtmp_configure_ssl_name(cf->pool, u->url, - &target->ssl_name) != NGX_OK) { + if (ngx_rtmp_relay_configure_ssl_name(cf->pool, u->url, + &target->ssl_name) != NGX_OK) { return NGX_CONF_ERROR; } } @@ -2216,8 +2212,9 @@ ngx_rtmp_ssl_name(ngx_rtmp_session_t *rs, ngx_rtmp_relay_target_t *target) return NGX_OK; } -static ngx_int_t -ngx_rtmp_configure_ssl_name(ngx_pool_t *pool, ngx_str_t url, ngx_str_t *ssl_name) +ngx_int_t +ngx_rtmp_relay_configure_ssl_name(ngx_pool_t *pool, ngx_str_t url, + ngx_str_t *ssl_name) { u_char *host, *port, *last, *uri, *args, *p; @@ -2269,8 +2266,8 @@ ngx_rtmp_configure_ssl_name(ngx_pool_t *pool, ngx_str_t url, ngx_str_t *ssl_name } -static ngx_int_t -ngx_rtmp_configure_ssl(ngx_conf_t *cf, ngx_rtmp_relay_app_conf_t *racf, +ngx_int_t +ngx_rtmp_relay_configure_ssl(ngx_conf_t *cf, ngx_rtmp_relay_app_conf_t *racf, ngx_rtmp_relay_target_t *target) { ngx_pool_cleanup_t *cln; diff --git a/ngx_rtmp_relay_module.h b/ngx_rtmp_relay_module.h index 52da82962..f49475972 100644 --- a/ngx_rtmp_relay_module.h +++ b/ngx_rtmp_relay_module.h @@ -114,5 +114,15 @@ ngx_int_t ngx_rtmp_relay_pull(ngx_rtmp_session_t *s, ngx_str_t *name, ngx_int_t ngx_rtmp_relay_push(ngx_rtmp_session_t *s, ngx_str_t *name, ngx_rtmp_relay_target_t *target); +#if (NGX_RTMP_SSL) + +ngx_int_t ngx_rtmp_relay_configure_ssl_name(ngx_pool_t *pool, ngx_str_t url, + ngx_str_t *ssl_name); +ngx_int_t ngx_rtmp_relay_configure_ssl(ngx_conf_t *cf, + ngx_rtmp_relay_app_conf_t *racf, + ngx_rtmp_relay_target_t *target); + +#endif + #endif /* _NGX_RTMP_RELAY_H_INCLUDED_ */ From 14a38fb7de96b09c7f7ed9ed63eea1ebec9c3722 Mon Sep 17 00:00:00 2001 From: Emmanuel Mathi-Amorim Date: Thu, 14 Apr 2022 22:01:30 -0400 Subject: [PATCH 5/5] fix SSL name computed incorrectly in certain cases Remove the custom logic for computing the SSL name as it is unnessary and replace it with the standard URL parsing logic found in NGINX. Also add one missing #undef directive. --- ngx_rtmp_notify_module.c | 17 +++++++-- ngx_rtmp_relay_module.c | 76 ++++++++++------------------------------ ngx_rtmp_relay_module.h | 2 -- 3 files changed, 32 insertions(+), 63 deletions(-) diff --git a/ngx_rtmp_notify_module.c b/ngx_rtmp_notify_module.c index 806b37d11..ca2797165 100644 --- a/ngx_rtmp_notify_module.c +++ b/ngx_rtmp_notify_module.c @@ -1450,9 +1450,6 @@ ngx_rtmp_notify_resolve_handler(ngx_resolver_ctx_t *ctx) ngx_resolve_name_done(ctx); - ngx_rtmp_relay_configure_ssl_name(s->connection->pool, - target->url.url, - &target->ssl_name); ngx_rtmp_relay_push(s, &push_pull_ctx->name, target); return; @@ -1630,6 +1627,20 @@ ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s, return NGX_ERROR; } +#if (NGX_RTMP_SSL) + if (target->is_rtmps) { + /* ssl_name must be NULL terminated, so duplicate it */ + target->ssl_name.data = ngx_pnalloc(s->connection->pool, u->host.len + 1); + if (target->ssl_name.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(target->ssl_name.data, u->host.data, u->host.len); + target->ssl_name.data[u->host.len] = '\0'; + target->ssl_name.len = u->host.len; + } +#endif + if (u->naddrs == 0) { /* need to resolve the name */ temp.name = u->host; diff --git a/ngx_rtmp_relay_module.c b/ngx_rtmp_relay_module.c index 1ad488d8f..8c05acf09 100644 --- a/ngx_rtmp_relay_module.c +++ b/ngx_rtmp_relay_module.c @@ -1823,11 +1823,6 @@ ngx_rtmp_relay_push_pull(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) target->is_rtmps = 1; target->ssl_server_name = NGX_CONF_UNSET; target->ssl_verify = NGX_CONF_UNSET; - - if (ngx_rtmp_relay_configure_ssl_name(cf->pool, u->url, - &target->ssl_name) != NGX_OK) { - return NGX_CONF_ERROR; - } } #endif @@ -1840,6 +1835,22 @@ ngx_rtmp_relay_push_pull(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } +#if (NGX_RTMP_SSL) + + if (target->is_rtmps) { + /* ssl_name must be NULL terminated, so duplicate it */ + target->ssl_name.data = ngx_pnalloc(cf->pool, u->host.len + 1); + if (target->ssl_name.data == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memcpy(target->ssl_name.data, u->host.data, u->host.len); + target->ssl_name.data[u->host.len] = '\0'; + target->ssl_name.len = u->host.len; + } + +#endif + value += 2; for (i = 2; i < cf->args->nelts; ++i, ++value) { p = ngx_strlchr(value->data, value->data + value->len, '='); @@ -1908,6 +1919,8 @@ ngx_rtmp_relay_push_pull(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) NGX_RTMP_RELAY_FLAG_PAR("ssl_server_name", ssl_server_name); NGX_RTMP_RELAY_FLAG_PAR("ssl_verify", ssl_verify); } + +#undef NGX_RTMP_RELAY_FLAG_PAR #endif @@ -2212,59 +2225,6 @@ ngx_rtmp_ssl_name(ngx_rtmp_session_t *rs, ngx_rtmp_relay_target_t *target) return NGX_OK; } -ngx_int_t -ngx_rtmp_relay_configure_ssl_name(ngx_pool_t *pool, ngx_str_t url, - ngx_str_t *ssl_name) -{ - u_char *host, *port, *last, *uri, *args, *p; - - if (url.len == 0) { - goto no_ssl_name; - } - - host = url.data; - last = host + url.len; - - if (url.data[0] == '[') { - /* found a literal IPv6 address */ - goto no_ssl_name; - } - - port = ngx_strlchr(host, last, ':'); - uri = ngx_strlchr(host, last, '/'); - args = ngx_strlchr(host, last, '?'); - - /* find the end of the hostname part of the url */ - if (port) { - last = port; - } else if (uri) { - last = uri; - } else if (args) { - last = args; - } - - if (ngx_inet_addr(host, last - host) != INADDR_NONE) { - goto no_ssl_name; - } - - p = ngx_pnalloc(pool, (last - host) + 1); - if (p == NULL) { - goto err; - } - - (void) ngx_cpystrn(p, host, (last - host) + 1); - - ssl_name->len = last - host; - ssl_name->data = p; - return NGX_OK; - -no_ssl_name: - return NGX_OK; - -err: - return NGX_ERROR; -} - ngx_int_t ngx_rtmp_relay_configure_ssl(ngx_conf_t *cf, ngx_rtmp_relay_app_conf_t *racf, diff --git a/ngx_rtmp_relay_module.h b/ngx_rtmp_relay_module.h index f49475972..dc8adfe3c 100644 --- a/ngx_rtmp_relay_module.h +++ b/ngx_rtmp_relay_module.h @@ -116,8 +116,6 @@ ngx_int_t ngx_rtmp_relay_push(ngx_rtmp_session_t *s, ngx_str_t *name, #if (NGX_RTMP_SSL) -ngx_int_t ngx_rtmp_relay_configure_ssl_name(ngx_pool_t *pool, ngx_str_t url, - ngx_str_t *ssl_name); ngx_int_t ngx_rtmp_relay_configure_ssl(ngx_conf_t *cf, ngx_rtmp_relay_app_conf_t *racf, ngx_rtmp_relay_target_t *target);