Open vislee opened 5 years ago
业务上很多特殊的需求还是需要修改nginx的代码来实现,而这些特殊的需求又不通用,nginx上根本不会支持。
修改nginx代码在proxy_cache_path 添加prefix=$var 支持缓存文件后缀名。 配置实例:
proxy_cache_path
prefix=$var
proxy_cache_path ./cache levels=1:2 prefix=$host keys_zone=test:10m max_size=1g;
测试:
./cache/e/0b/www.test.comd0431adbaa72e1b38e0884b71c9d30be
diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h index f9e966409..7aa8a5f56 100644 --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -160,6 +160,8 @@ struct ngx_http_file_cache_s { ngx_path_t *path; + ngx_http_complex_value_t prefix; + off_t max_size; size_t bsize; diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index 3b2b68a26..1f9458313 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -933,6 +933,7 @@ static ngx_int_t ngx_http_file_cache_name(ngx_http_request_t *r, ngx_path_t *path) { u_char *p; + ngx_str_t prefix; ngx_http_cache_t *c; c = r->cache; @@ -941,8 +942,17 @@ ngx_http_file_cache_name(ngx_http_request_t *r, ngx_path_t *path) return NGX_OK; } + prefix.len = 0; + if (c->file_cache->prefix.value.len > 0) { + if (ngx_http_complex_value(r, &c->file_cache->prefix, &prefix) + != NGX_OK) + { + return NGX_ERROR; + } + } + c->file.name.len = path->name.len + 1 + path->len - + 2 * NGX_HTTP_CACHE_KEY_LEN; + + 2 * NGX_HTTP_CACHE_KEY_LEN + prefix.len; c->file.name.data = ngx_pnalloc(r->pool, c->file.name.len + 1); if (c->file.name.data == NULL) { @@ -952,6 +962,10 @@ ngx_http_file_cache_name(ngx_http_request_t *r, ngx_path_t *path) ngx_memcpy(c->file.name.data, path->name.data, path->name.len); p = c->file.name.data + path->name.len + 1 + path->len; + if (prefix.len > 0) { + ngx_memcpy(p, prefix.data, prefix.len); + p += prefix.len; + } p = ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN); *p = '\0'; @@ -2308,7 +2322,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) u_char *last, *p; time_t inactive; ssize_t size; - ngx_str_t s, name, *value; + ngx_str_t s, prefix, name, *value; ngx_int_t loader_files, manager_files; ngx_msec_t loader_sleep, manager_sleep, loader_threshold, manager_threshold; @@ -2316,6 +2330,8 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_array_t *caches; ngx_http_file_cache_t *cache, **ce; + ngx_http_compile_complex_value_t ccv; + cache = ngx_pcalloc(cf->pool, sizeof(ngx_http_file_cache_t)); if (cache == NULL) { return NGX_CONF_ERROR; @@ -2338,6 +2354,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) manager_sleep = 50; manager_threshold = 200; + prefix.len = 0; name.len = 0; size = 0; max_size = NGX_MAX_OFF_T_VALUE; @@ -2393,6 +2410,14 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } + if (ngx_strncmp(value[i].data, "prefix=", 7) == 0) { + + prefix.data = value[i].data + 7; + prefix.len = value[i].len - 7; + + continue; + } + if (ngx_strncmp(value[i].data, "use_temp_path=", 14) == 0) { if (ngx_strcmp(&value[i].data[14], "on") == 0) { @@ -2599,6 +2624,21 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) cache->inactive = inactive; cache->max_size = max_size; + // prefix + if (prefix.len > 0) { + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &prefix; + ccv.complex_value = &cache->prefix; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "error prefix \"%V\"", &prefix); + return NGX_CONF_ERROR; + } + } + caches = (ngx_array_t *) (confp + cmd->offset); ce = ngx_array_push(caches);
pre_cache_bypass
类似于proxy_cache_bypass指令。可以在lua中动态控制请求是否缓存。 注意:和proxy_cache_bypass 指令冲突。
proxy_cache_bypass
例如:
set $pre_cache_bypass "off"; access_lua_by_block { ... ngx.var.pre_cache_bypass = "cache" ... }
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c index 96f3ec69..7d0e19a6 100644 --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -247,9 +247,20 @@ ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_int_t ngx_http_test_predicates(ngx_http_request_t *r, ngx_array_t *predicates) { - ngx_str_t val; - ngx_uint_t i; + ngx_str_t val, name; + ngx_uint_t i, hash; ngx_http_complex_value_t *cv; + ngx_http_variable_value_t *vv; + + ngx_str_set(&name, "pre_cache_bypass"); + hash = ngx_hash_key(name.data, name.len); + vv = ngx_http_get_variable(r, &name, hash); + + if (vv != NULL && vv->valid && + vv->len == 3 && ngx_strncmp(vv->data, "off", 3) == 0) + { + return NGX_DECLINED; + } if (predicates == NULL) { return NGX_OK;
proxy_protocol
X-Forwarded-For
set_addr(addr)
patch:ngx_http_realip2_module
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index c827c015..138e7b0a 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -15,6 +15,120 @@ ngx_os_io_t ngx_io; static void ngx_drain_connections(ngx_cycle_t *cycle); +// =======tproxy by liwq (B)===== +#if (NGX_HAVE_TRANSPARENT_PROXY) +static ngx_int_t ngx_set_listen_transparent(ngx_cycle_t *cycle, + ngx_listening_t *ls); +static void ngx_set_inherited_transparent (ngx_cycle_t *cycle, + ngx_listening_t *ls); +#endif +// =======tproxy by liwq (E)===== + +// =======downgrade by liwq (B)===== +ngx_listening_t * +ngx_attach_listening(ngx_conf_t *cf, struct sockaddr *sockaddr, + socklen_t socklen) +{ + ngx_uint_t i, j; + ngx_listening_t *ls, *als = NULL; + size_t len; + struct sockaddr *sa = NULL; + u_char text[NGX_SOCKADDR_STRLEN]; + + ls = cf->cycle->listening.elts; + for (i = 0; i < cf->cycle->listening.nelts; i++) { + if (ls[i].mode == 0) { + continue; + } + + if (ngx_cmp_sockaddr(ls[i].sockaddr, ls[i].socklen, + sockaddr, socklen, 1) != NGX_OK) { + continue; + } + + als = ngx_palloc(cf->pool, sizeof(ngx_listening_t)); + ls[i].attach = als; + if (als == NULL) { + return NULL; + } + + if (ls[i].reuseport) { + for (j = i; j < cf->cycle->listening.nelts; j++) { + if (ngx_cmp_sockaddr(ls[j].sockaddr, + ls[j].socklen, sockaddr, socklen, 1) == NGX_OK) + { + ls[j].attach = als; + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, + "attach reuseport addr: %V to worker: %ui", + &ls[j].addr_text, ls[j].worker); + } + } + } + + ngx_memzero(als, sizeof(ngx_listening_t)); + + sa = ngx_palloc(cf->pool, socklen); + if (sa == NULL) { + return NULL; + } + + ngx_memcpy(sa, sockaddr, socklen); + + als->sockaddr = sa; + als->socklen = socklen; + + len = ngx_sock_ntop(sa, socklen, text, NGX_SOCKADDR_STRLEN, 1); + als->addr_text.len = len; + + switch (als->sockaddr->sa_family) { + #if (NGX_HAVE_INET6) + case AF_INET6: + als->addr_text_max_len = NGX_INET6_ADDRSTRLEN; + break; + #endif + #if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + als->addr_text_max_len = NGX_UNIX_ADDRSTRLEN; + len++; + break; + #endif + case AF_INET: + als->addr_text_max_len = NGX_INET_ADDRSTRLEN; + break; + default: + als->addr_text_max_len = NGX_SOCKADDR_STRLEN; + break; + } + + als->addr_text.data = ngx_pnalloc(cf->pool, len); + if (als->addr_text.data == NULL) { + return NULL; + } + + ngx_memcpy(als->addr_text.data, text, len); + + als->fd = (ngx_socket_t) -1; + als->type = SOCK_STREAM; + + als->backlog = NGX_LISTEN_BACKLOG; + als->rcvbuf = -1; + als->sndbuf = -1; + + #if (NGX_HAVE_SETFIB) + als->setfib = -1; + #endif + + #if (NGX_HAVE_TCP_FASTOPEN) + als->fastopen = -1; + #endif + + return als; + } + + return NULL; +} +// =======downgrade by liwq (B)===== ngx_listening_t * ngx_create_listening(ngx_conf_t *cf, struct sockaddr *sockaddr, @@ -375,6 +489,12 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) ls[i].deferred_accept = 1; #endif + +// =======tproxy by liwq (B)===== +#if (NGX_HAVE_TRANSPARENT_PROXY) + ngx_set_inherited_transparent(cycle, &ls[i]); +#endif +// =======tproxy by liwq (E)===== } return NGX_OK; @@ -701,6 +821,12 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle) } } +// =======tproxy by liwq (B)===== +#if (NGX_HAVE_TRANSPARENT_PROXY) + ngx_set_listen_transparent(cycle, &ls[i]); +#endif +// =======tproxy by liwq (E)===== + #if (NGX_HAVE_KEEPALIVE_TUNABLE) if (ls[i].keepidle) { @@ -1479,3 +1605,196 @@ ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text) return NGX_ERROR; } + +// =======tproxy by liwq (B)===== +#if (NGX_HAVE_TRANSPARENT_PROXY) + +static ngx_int_t +ngx_set_listen_transparent(ngx_cycle_t *cycle, ngx_listening_t *ls) +{ + int value; + + value = ls->transparent; + +#if defined(SO_BINDANY) + + if (setsockopt(ls->fd, SOL_SOCKET, SO_BINDANY, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "setsockopt(SO_BINDANY) failed"); + return NGX_ERROR; + } + +#else + + switch (ls->sockaddr->sa_family) { + + case AF_INET: + +#if defined(IP_TRANSPARENT) + + if (setsockopt(ls->fd, IPPROTO_IP, IP_TRANSPARENT, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "setsockopt(IP_TRANSPARENT) failed"); + return NGX_ERROR; + } + +#elif defined(IP_BINDANY) + + if (setsockopt(ls->fd, IPPROTO_IP, IP_BINDANY, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "setsockopt(IP_BINDANY) failed"); + return NGX_ERROR; + } + +#endif + + break; + +#if (NGX_HAVE_INET6) + + case AF_INET6: + +#if defined(IPV6_TRANSPARENT) + + if (setsockopt(ls->fd, IPPROTO_IPV6, IPV6_TRANSPARENT, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "setsockopt(IPV6_TRANSPARENT) failed"); + return NGX_ERROR; + } + +#elif defined(IPV6_BINDANY) + + if (setsockopt(ls->fd, IPPROTO_IPV6, IPV6_BINDANY, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "setsockopt(IPV6_BINDANY) failed"); + return NGX_ERROR; + } + +#else + + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "could not enable transparent listen for IPv6 " + "on this platform"); + + return NGX_ERROR; + +#endif + + break; + +#endif /* NGX_HAVE_INET6 */ + + } + +#endif /* SO_BINDANY */ + + return NGX_OK; +} + + +static void +ngx_set_inherited_transparent(ngx_cycle_t *cycle, ngx_listening_t *ls) +{ + int value; + socklen_t olen; + + olen = sizeof(int); + +#if defined(SO_BINDANY) + + if (getsockopt(ls->fd, SOL_SOCKET, SO_BINDANY, + (void *) &value, &olen) == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "getsockopt(SO_BINDANY) failed"); + return; + } else { + ls->transparent = value ? 1 : 0; + } + +#else + + switch (ls->sockaddr->sa_family) { + + case AF_INET: + +#if defined(IP_TRANSPARENT) + + if (getsockopt(ls->fd, IPPROTO_IP, IP_TRANSPARENT, + (void *) &value, &olen) == -1) + { + ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_socket_errno, + "getsockopt(IP_TRANSPARENT) failed"); + return; + } else { + ls->transparent = value ? 1 : 0; + } + +#elif defined(IP_BINDANY) + + if (getsockopt(ls->fd, IPPROTO_IP, IP_BINDANY, + (void *) &value, &olen) == -1) + { + ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_socket_errno, + "getsockopt(IP_BINDANY) failed"); + return; + } else { + ls->transparent = value ? 1 : 0; + } + +#endif + + break; + +#if (NGX_HAVE_INET6) + + case AF_INET6: + +#if defined(IPV6_TRANSPARENT) + + if (getsockopt(ls->fd, IPPROTO_IPV6, IPV6_TRANSPARENT, + (void *) &value, &olen) == -1) + { + ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_socket_errno, + "getsockopt(IPV6_TRANSPARENT) failed"); + return; + } else { + ls->transparent = value ? 1 : 0; + } + +#elif defined(IPV6_BINDANY) + + if (getsockopt(ls->fd, IPPROTO_IPV6, IPV6_BINDANY, + (void *) &value, &olen) == -1) + { + ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_socket_errno, + "getsockopt(IPV6_BINDANY) failed"); + return; + } else { + ls->transparent = value ? 1 : 0; + } + +#endif + + break; + +#endif /* NGX_HAVE_INET6 */ + + } + +#endif /* SO_BINDANY */ + + return; +} +#endif +// =======tproxy by liwq (E)===== diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index 7f358898..692d6f6a 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -53,10 +53,21 @@ struct ngx_listening_s { ngx_uint_t worker; +// =======downgrade by liwq (B)===== + ngx_listening_t *attach; + ngx_uint_t mode; +// =======downgrade by liwq (E)===== + unsigned open:1; unsigned remain:1; unsigned ignore:1; +// =======tproxy by liwq (B)===== +#if (NGX_HAVE_TRANSPARENT_PROXY) + unsigned transparent:1; +#endif +// =======tproxy by liwq (E)===== + unsigned bound:1; /* already bound */ unsigned inherited:1; /* inherited from previous process */ unsigned nonblocking_accept:1; @@ -214,7 +225,11 @@ struct ngx_connection_s { c->log->log_level = l->log_level; \ } - +// =======downgrade by liwq (B)===== +ngx_listening_t * +ngx_attach_listening(ngx_conf_t *cf, struct sockaddr *sockaddr, + socklen_t socklen); +// =======downgrade by liwq (E)===== ngx_listening_t *ngx_create_listening(ngx_conf_t *cf, struct sockaddr *sockaddr, socklen_t socklen); ngx_int_t ngx_clone_listening(ngx_conf_t *cf, ngx_listening_t *ls); diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 6305ac21..4de3d097 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -243,6 +243,15 @@ static ngx_command_t ngx_http_ssl_commands[] = { offsetof(ngx_http_ssl_srv_conf_t, stapling_verify), NULL }, +// =======downgrade by liwq (B)===== + { ngx_string("ssl_sni"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_array_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, ssl_sni), + NULL }, +// =======downgrade by liwq (E)===== + ngx_null_command }; @@ -570,6 +579,11 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) sscf->stapling = NGX_CONF_UNSET; sscf->stapling_verify = NGX_CONF_UNSET; + +// =======downgrade by liwq (B)===== + sscf->ssl_sni = NGX_CONF_UNSET_PTR; +// =======downgrade by liwq (E)===== + return sscf; } @@ -645,6 +659,10 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->stapling_responder, prev->stapling_responder, ""); +// =======downgrade by liwq (B)===== + ngx_conf_merge_ptr_value(conf->ssl_sni, prev->ssl_sni, NULL); +// =======downgrade by liwq (E)===== + conf->ssl.log = cf->log; if (conf->enable) { diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h index b97417a2..10c6de1b 100644 --- a/src/http/modules/ngx_http_ssl_module.h +++ b/src/http/modules/ngx_http_ssl_module.h @@ -57,6 +57,10 @@ typedef struct { ngx_str_t stapling_file; ngx_str_t stapling_responder; +// =======downgrade by liwq (B)===== + ngx_array_t *ssl_sni; +// =======downgrade by liwq (E)===== + u_char *file; ngx_uint_t line; } ngx_http_ssl_srv_conf_t; diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 9d8b6d79..483943ac 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -1772,6 +1772,16 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr) ls->reuseport = addr->opt.reuseport; #endif +// =======downgrade by liwq (B)===== + ls->mode = NGX_HTTP_MODULE; +// =======downgrade by liwq (E)===== + +// =======tproxy by liwq (B)===== +#if (NGX_HAVE_TRANSPARENT_PROXY) + ls->transparent = addr->opt.transparent; +#endif +// =======tproxy by liwq (E)===== + return ls; } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 57a47427..c9027208 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -4067,6 +4067,27 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) continue; } + // =======tproxy by liwq (B)===== + if (ngx_strcmp(value[n].data, "transparent") == 0) { +#if (NGX_HAVE_TRANSPARENT_PROXY) + if (lsopt.wildcard) { + lsopt.set = 1; + lsopt.bind = 1; + lsopt.transparent = 1; + } else { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "transparent listen only supported wildcard addr, " + "this addr ignored"); + } +#else + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "transparent listen is not supported " + "on this platform, ignored"); +#endif + continue; + } + // =======tproxy by liwq (E)===== + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[n]); return NGX_CONF_ERROR; diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index a6128b54..8ecbce51 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -81,6 +81,12 @@ typedef struct { unsigned reuseport:1; unsigned so_keepalive:2; unsigned proxy_protocol:1; +// =======tproxy by liwq (B)===== +#if (NGX_HAVE_TRANSPARENT_PROXY) + unsigned transparent:1; /* unsigned transparent:1; */ +#endif +// =======tproxy by liwq (E)===== + int backlog; int rcvbuf; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 0fa7f08a..35783d44 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -9,6 +9,11 @@ #include <ngx_core.h> #include <ngx_http.h> +// =======downgrade by liwq (B)===== +extern void ngx_stream_init_connection(ngx_connection_t *c); +extern ngx_int_t ngx_stream_ssl_get_server_name(ngx_pool_t *pool, + ngx_log_t *log, u_char *pos, u_char *last, ngx_str_t *server_name); +// =======downgrade by liwq (E)===== static void ngx_http_wait_request_handler(ngx_event_t *ev); static void ngx_http_process_request_line(ngx_event_t *rev); @@ -757,6 +762,43 @@ ngx_http_create_request(ngx_connection_t *c) #if (NGX_HTTP_SSL) +// =======downgrade by liwq (B)===== +static ngx_int_t +ngx_http_check_cert(ngx_array_t *ssl_sni, ngx_str_t *sni) +{ + ngx_uint_t i; + ngx_str_t *ss; + + if (ssl_sni == NULL) { + return NGX_ERROR; + } + + if (sni == NULL || sni->len == 0) { + return NGX_ERROR; + } + + ss = ssl_sni->elts; + for (i = 0; i < ssl_sni->nelts; i++) { + if (ss[i].len == sni->len && + ngx_memcmp(ss[i].data, sni->data, sni->len) == 0) { + + return NGX_OK; + } + + if (ss[i].len > 2 && ss[i].len <= sni->len && + ss[i].data[0] == '*' && ss[i].data[1] == '.' && + ngx_memcmp(ss[i].data + 1, sni->data + (sni->len - ss[i].len + 1), + ss[i].len - 1) == 0 ) { + + return NGX_OK; + } + + } + + return NGX_ERROR; +} +// =======downgrade by liwq (E)===== + static void ngx_http_ssl_handshake(ngx_event_t *rev) { @@ -770,6 +812,13 @@ ngx_http_ssl_handshake(ngx_event_t *rev) ngx_http_ssl_srv_conf_t *sscf; ngx_http_core_loc_conf_t *clcf; +// =======downgrade by liwq (B)===== + u_char pb[1024+1]; + ssize_t m; + ngx_int_t rt; + ngx_str_t sni; +// =======downgrade by liwq (E)===== + c = rev->data; hc = c->data; @@ -873,6 +922,34 @@ ngx_http_ssl_handshake(ngx_event_t *rev) sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); +// =======downgrade by liwq (B)===== + if (c->listening->attach && sscf->ssl_sni) { + m = recv(c->fd, (char *) pb, 1024, MSG_PEEK); + // rt = ngx_http_ssl_sni(pb, m, &sni); + + rt = ngx_stream_ssl_get_server_name(c->pool, c->log, + pb, pb+m, &sni); + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, + "https downgrade: %d, %d, SNI hostname %V", + m, rt, &sni); + + if (rt == NGX_OK && + ngx_http_check_cert(sscf->ssl_sni, &sni) == NGX_ERROR) { + + if (c->log->data != NULL) { + ngx_pfree(c->pool, c->log->data); + } + if (c->data != NULL) { + ngx_pfree(c->pool, c->data); + } + + ngx_stream_init_connection(c); + return; + } + } +// =======downgrade by liwq (E)===== + if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER) != NGX_OK) { diff --git a/src/stream/ngx_stream.c b/src/stream/ngx_stream.c index 0efbda89..3dbf9aed 100644 --- a/src/stream/ngx_stream.c +++ b/src/stream/ngx_stream.c @@ -476,8 +476,22 @@ ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) continue; } - ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, - addr[i].opt.socklen); +// =======downgrade by liwq (B)===== + if (addr[i].opt.attach) { + ls = ngx_attach_listening(cf, &addr[i].opt.sockaddr.sockaddr, + addr[i].opt.socklen); + if (ls == NULL) { + ngx_log_error(NGX_LOG_ERR, cf->log, 0, + "stream attach error"); + } + } else { + ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, + addr[i].opt.socklen); + } +// =======downgrade by liwq (E)===== + + // ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, + // addr[i].opt.socklen); if (ls == NULL) { return NGX_CONF_ERROR; } diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h index 09d24593..182148f5 100644 --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -47,6 +47,10 @@ typedef struct { /* server ctx */ ngx_stream_conf_ctx_t *ctx; +// =======downgrade by liwq (B)===== + unsigned attach:1; +// =======downgrade by liwq (E)===== + unsigned bind:1; unsigned wildcard:1; unsigned ssl:1; diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c index 272708d6..cd66ba7d 100644 --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -628,6 +628,13 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } #endif +// =======downgrade by liwq (B)===== + if (ngx_strcmp(value[i].data, "attach") == 0) { + ls->attach = 1; + continue; + } +// =======downgrade by liwq (E)===== + if (ngx_strcmp(value[i].data, "bind") == 0) { ls->bind = 1; continue; @@ -864,6 +871,17 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } } +// =======downgrade by liwq (B)===== + if (ls->attach) { + if (ls->type == SOCK_DGRAM) { + return "\"attach\" parameter is incompatible with \"udp\""; + } + if (ls->bind) { + return "\"attach\" parameter is incompatible with \"bind\""; + } + } +// =======downgrade by liwq (B)===== + als = cmcf->listen.elts; for (i = 0; i < cmcf->listen.nelts - 1; i++) { diff --git a/src/stream/ngx_stream_handler.c b/src/stream/ngx_stream_handler.c index 2b6881bc..69ba8068 100644 --- a/src/stream/ngx_stream_handler.c +++ b/src/stream/ngx_stream_handler.c @@ -40,7 +40,15 @@ ngx_stream_init_connection(ngx_connection_t *c) /* find the server configuration for the address:port */ - port = c->listening->servers; +// =======downgrade by liwq (B)===== + if (c->listening->mode && c->listening->attach) { + port = c->listening->attach->servers; + } else { + port = c->listening->servers; + } +// =======downgrade by liwq (E)===== + + // port = c->listening->servers; if (port->naddrs > 1) { diff --git a/src/stream/ngx_stream_ssl_preread_module.c b/src/stream/ngx_stream_ssl_preread_module.c index e3d11fd9..86833a04 100644 --- a/src/stream/ngx_stream_ssl_preread_module.c +++ b/src/stream/ngx_stream_ssl_preread_module.c @@ -360,6 +360,53 @@ ngx_stream_ssl_preread_parse_record(ngx_stream_ssl_preread_ctx_t *ctx, } +// =======downgrade by liwq (B)===== +ngx_int_t +ngx_stream_ssl_get_server_name(ngx_pool_t *pool, ngx_log_t *log, + u_char *pos, u_char *last, ngx_str_t *server_name) +{ + ngx_stream_ssl_preread_ctx_t ctx; + ngx_int_t rc; + size_t len; + + ngx_memzero(&ctx, sizeof(ngx_stream_ssl_preread_ctx_t)); + + ctx.pool = pool; + ctx.log = log; + ctx.pos = pos; + + if (last - pos < 5) { + return NGX_ERROR; + } + + if (pos[0] != 0x16) { + return NGX_ERROR; + } + + if (pos[1] != 3) { + return NGX_ERROR; + } + + len = (pos[3] << 8) + pos[4]; + + if ((size_t) (last - pos) < len + 5) { + return NGX_ERROR; + } + + pos += 5; + + rc = ngx_stream_ssl_preread_parse_record(&ctx, pos, pos + len); + if (rc != NGX_OK) { + return rc; + } + + *server_name = ctx.host; + + return NGX_OK; +} +// =======downgrade by liwq (E)===== + + static ngx_int_t ngx_stream_ssl_preread_server_name_variable(ngx_stream_session_t *s, ngx_variable_value_t *v, uintptr_t data)
概述
业务上很多特殊的需求还是需要修改nginx的代码来实现,而这些特殊的需求又不通用,nginx上根本不会支持。
patch
修改nginx代码在
proxy_cache_path
添加prefix=$var
支持缓存文件后缀名。 配置实例:测试:
pre_cache_bypass
控制是否缓存。类似于
proxy_cache_bypass
指令。可以在lua中动态控制请求是否缓存。 注意:和proxy_cache_bypass
指令冲突。例如:
proxy_protocol
协议会带代理认为的客户端IP,http协议也会通过X-Forwarded-For
带真实客户端IP。 或者真实客户端IP的获取会在lua中有自己特殊的获取逻辑,然后通过set_addr(addr)
设置。不影响日志打印。patch:ngx_http_realip2_module