leevis.com
leevis.com copied to clipboard
给nginx添加的特殊功能
概述
业务上很多特殊的需求还是需要修改nginx的代码来实现,而这些特殊的需求又不通用,nginx上根本不会支持。
patch
- patch 1: 缓存文件添加前缀。
修改nginx代码在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);
- patch 2: 通过变量
pre_cache_bypass控制是否缓存。
类似于proxy_cache_bypass指令。可以在lua中动态控制请求是否缓存。
注意:和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;
- patch 3: 修改真实客户端IP
正常nginx的realip模块只会替换一次真实的客户端IP。例如前面代理通过
proxy_protocol协议会带代理认为的客户端IP,http协议也会通过X-Forwarded-For带真实客户端IP。 或者真实客户端IP的获取会在lua中有自己特殊的获取逻辑,然后通过set_addr(addr)设置。不影响日志打印。
patch:ngx_http_realip2_module
- patch 4: 全透明代理和无证书流量透传
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)