#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#define NGX_HTTP_PROXY_COOKIE_SECURE …
#define NGX_HTTP_PROXY_COOKIE_SECURE_ON …
#define NGX_HTTP_PROXY_COOKIE_SECURE_OFF …
#define NGX_HTTP_PROXY_COOKIE_HTTPONLY …
#define NGX_HTTP_PROXY_COOKIE_HTTPONLY_ON …
#define NGX_HTTP_PROXY_COOKIE_HTTPONLY_OFF …
#define NGX_HTTP_PROXY_COOKIE_SAMESITE …
#define NGX_HTTP_PROXY_COOKIE_SAMESITE_STRICT …
#define NGX_HTTP_PROXY_COOKIE_SAMESITE_LAX …
#define NGX_HTTP_PROXY_COOKIE_SAMESITE_NONE …
#define NGX_HTTP_PROXY_COOKIE_SAMESITE_OFF …
ngx_http_proxy_main_conf_t;
ngx_http_proxy_rewrite_t;
ngx_http_proxy_rewrite_pt;
struct ngx_http_proxy_rewrite_s { … };
ngx_http_proxy_cookie_flags_t;
ngx_http_proxy_vars_t;
ngx_http_proxy_headers_t;
ngx_http_proxy_loc_conf_t;
ngx_http_proxy_ctx_t;
static ngx_int_t ngx_http_proxy_eval(ngx_http_request_t *r,
ngx_http_proxy_ctx_t *ctx, ngx_http_proxy_loc_conf_t *plcf);
#if (NGX_HTTP_CACHE)
static ngx_int_t ngx_http_proxy_create_key(ngx_http_request_t *r);
#endif
static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_proxy_body_output_filter(void *data, ngx_chain_t *in);
static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r);
static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r);
static ngx_int_t ngx_http_proxy_input_filter_init(void *data);
static ngx_int_t ngx_http_proxy_copy_filter(ngx_event_pipe_t *p,
ngx_buf_t *buf);
static ngx_int_t ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p,
ngx_buf_t *buf);
static ngx_int_t ngx_http_proxy_non_buffered_copy_filter(void *data,
ssize_t bytes);
static ngx_int_t ngx_http_proxy_non_buffered_chunked_filter(void *data,
ssize_t bytes);
static void ngx_http_proxy_abort_request(ngx_http_request_t *r);
static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
ngx_int_t rc);
static ngx_int_t ngx_http_proxy_host_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t
ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t
ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_proxy_internal_chunked_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r,
ngx_table_elt_t *h, size_t prefix);
static ngx_int_t ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r,
ngx_table_elt_t *h);
static ngx_int_t ngx_http_proxy_parse_cookie(ngx_str_t *value,
ngx_array_t *attrs);
static ngx_int_t ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r,
ngx_str_t *value, ngx_array_t *rewrites);
static ngx_int_t ngx_http_proxy_rewrite_cookie_flags(ngx_http_request_t *r,
ngx_array_t *attrs, ngx_array_t *flags);
static ngx_int_t ngx_http_proxy_edit_cookie_flags(ngx_http_request_t *r,
ngx_array_t *attrs, ngx_uint_t flags);
static ngx_int_t ngx_http_proxy_rewrite(ngx_http_request_t *r,
ngx_str_t *value, size_t prefix, size_t len, ngx_str_t *replacement);
static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
static void *ngx_http_proxy_create_main_conf(ngx_conf_t *cf);
static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
static ngx_int_t ngx_http_proxy_init_headers(ngx_conf_t *cf,
ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_headers_t *headers,
ngx_keyval_t *default_headers);
static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_proxy_cookie_flags(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#if (NGX_HTTP_CACHE)
static char *ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#endif
#if (NGX_HTTP_SSL)
static char *ngx_http_proxy_ssl_password_file(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
#endif
static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data);
#if (NGX_HTTP_SSL)
static char *ngx_http_proxy_ssl_conf_command_check(ngx_conf_t *cf, void *post,
void *data);
#endif
static ngx_int_t ngx_http_proxy_rewrite_regex(ngx_conf_t *cf,
ngx_http_proxy_rewrite_t *pr, ngx_str_t *regex, ngx_uint_t caseless);
#if (NGX_HTTP_SSL)
static ngx_int_t ngx_http_proxy_merge_ssl(ngx_conf_t *cf,
ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_loc_conf_t *prev);
static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf,
ngx_http_proxy_loc_conf_t *plcf);
#endif
static void ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v);
static ngx_conf_post_t ngx_http_proxy_lowat_post = …;
static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = …;
#if (NGX_HTTP_SSL)
static ngx_conf_bitmask_t ngx_http_proxy_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 }
};
static ngx_conf_post_t ngx_http_proxy_ssl_conf_command_post =
{ ngx_http_proxy_ssl_conf_command_check };
#endif
static ngx_conf_enum_t ngx_http_proxy_http_version[] = …;
ngx_module_t ngx_http_proxy_module;
static ngx_command_t ngx_http_proxy_commands[] = …;
static ngx_http_module_t ngx_http_proxy_module_ctx = …;
ngx_module_t ngx_http_proxy_module = …;
static char ngx_http_proxy_version[] = …;
static char ngx_http_proxy_version_11[] = …;
static ngx_keyval_t ngx_http_proxy_headers[] = …;
static ngx_str_t ngx_http_proxy_hide_headers[] = …;
#if (NGX_HTTP_CACHE)
static ngx_keyval_t ngx_http_proxy_cache_headers[] = …;
#endif
static ngx_http_variable_t ngx_http_proxy_vars[] = …;
static ngx_path_init_t ngx_http_proxy_temp_path = …;
static ngx_conf_bitmask_t ngx_http_proxy_cookie_flags_masks[] = …;
static ngx_int_t
ngx_http_proxy_handler(ngx_http_request_t *r)
{ … }
static ngx_int_t
ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
ngx_http_proxy_loc_conf_t *plcf)
{ … }
#if (NGX_HTTP_CACHE)
static ngx_int_t
ngx_http_proxy_create_key(ngx_http_request_t *r)
{ … }
#endif
static ngx_int_t
ngx_http_proxy_create_request(ngx_http_request_t *r)
{ … }
static ngx_int_t
ngx_http_proxy_reinit_request(ngx_http_request_t *r)
{ … }
static ngx_int_t
ngx_http_proxy_body_output_filter(void *data, ngx_chain_t *in)
{ … }
static ngx_int_t
ngx_http_proxy_process_status_line(ngx_http_request_t *r)
{ … }
static ngx_int_t
ngx_http_proxy_process_header(ngx_http_request_t *r)
{ … }
static ngx_int_t
ngx_http_proxy_input_filter_init(void *data)
{ … }
static ngx_int_t
ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
{ … }
static ngx_int_t
ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
{ … }
static ngx_int_t
ngx_http_proxy_non_buffered_copy_filter(void *data, ssize_t bytes)
{ … }
static ngx_int_t
ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
{ … }
static void
ngx_http_proxy_abort_request(ngx_http_request_t *r)
{ … }
static void
ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
{ … }
static ngx_int_t
ngx_http_proxy_host_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{ … }
static ngx_int_t
ngx_http_proxy_port_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{ … }
static ngx_int_t
ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{ … }
static ngx_int_t
ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{ … }
static ngx_int_t
ngx_http_proxy_internal_chunked_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{ … }
static ngx_int_t
ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
size_t prefix)
{ … }
static ngx_int_t
ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r, ngx_table_elt_t *h)
{ … }
static ngx_int_t
ngx_http_proxy_parse_cookie(ngx_str_t *value, ngx_array_t *attrs)
{ … }
static ngx_int_t
ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r, ngx_str_t *value,
ngx_array_t *rewrites)
{ … }
static ngx_int_t
ngx_http_proxy_rewrite_cookie_flags(ngx_http_request_t *r, ngx_array_t *attrs,
ngx_array_t *flags)
{ … }
static ngx_int_t
ngx_http_proxy_edit_cookie_flags(ngx_http_request_t *r, ngx_array_t *attrs,
ngx_uint_t flags)
{ … }
static ngx_int_t
ngx_http_proxy_rewrite_complex_handler(ngx_http_request_t *r, ngx_str_t *value,
size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
{ … }
#if (NGX_PCRE)
static ngx_int_t
ngx_http_proxy_rewrite_regex_handler(ngx_http_request_t *r, ngx_str_t *value,
size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
{ … }
#endif
static ngx_int_t
ngx_http_proxy_rewrite_domain_handler(ngx_http_request_t *r, ngx_str_t *value,
size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
{ … }
static ngx_int_t
ngx_http_proxy_rewrite(ngx_http_request_t *r, ngx_str_t *value, size_t prefix,
size_t len, ngx_str_t *replacement)
{ … }
static ngx_int_t
ngx_http_proxy_add_variables(ngx_conf_t *cf)
{ … }
static void *
ngx_http_proxy_create_main_conf(ngx_conf_t *cf)
{ … }
static void *
ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
{ … }
static char *
ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{ … }
static ngx_int_t
ngx_http_proxy_init_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
ngx_http_proxy_headers_t *headers, ngx_keyval_t *default_headers)
{ … }
static char *
ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ … }
static char *
ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ … }
static char *
ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ … }
static char *
ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ … }
static char *
ngx_http_proxy_cookie_flags(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ … }
static ngx_int_t
ngx_http_proxy_rewrite_regex(ngx_conf_t *cf, ngx_http_proxy_rewrite_t *pr,
ngx_str_t *regex, ngx_uint_t caseless)
{ … }
static char *
ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ … }
#if (NGX_HTTP_CACHE)
static char *
ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ … }
static char *
ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{ … }
#endif
#if (NGX_HTTP_SSL)
static char *
ngx_http_proxy_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_proxy_loc_conf_t *plcf = conf;
ngx_str_t *value;
if (plcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) {
return "is duplicate";
}
value = cf->args->elts;
plcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
if (plcf->upstream.ssl_passwords == NULL) {
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
#endif
static char *
ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data)
{ … }
#if (NGX_HTTP_SSL)
static char *
ngx_http_proxy_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#else
return NGX_CONF_OK;
#endif
}
static ngx_int_t
ngx_http_proxy_merge_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
ngx_http_proxy_loc_conf_t *prev)
{
ngx_uint_t preserve;
if (conf->ssl_protocols == 0
&& conf->ssl_ciphers.data == NULL
&& conf->upstream.ssl_certificate == NGX_CONF_UNSET_PTR
&& conf->upstream.ssl_certificate_key == NGX_CONF_UNSET_PTR
&& conf->upstream.ssl_passwords == NGX_CONF_UNSET_PTR
&& conf->upstream.ssl_verify == NGX_CONF_UNSET
&& conf->ssl_verify_depth == NGX_CONF_UNSET_UINT
&& conf->ssl_trusted_certificate.data == NULL
&& conf->ssl_crl.data == NULL
&& conf->upstream.ssl_session_reuse == NGX_CONF_UNSET
&& conf->ssl_conf_commands == NGX_CONF_UNSET_PTR)
{
if (prev->upstream.ssl) {
conf->upstream.ssl = prev->upstream.ssl;
return NGX_OK;
}
preserve = 1;
} else {
preserve = 0;
}
conf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
if (conf->upstream.ssl == NULL) {
return NGX_ERROR;
}
conf->upstream.ssl->log = cf->log;
if (preserve) {
prev->upstream.ssl = conf->upstream.ssl;
}
return NGX_OK;
}
static ngx_int_t
ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
{
ngx_pool_cleanup_t *cln;
if (plcf->upstream.ssl->ctx) {
return NGX_OK;
}
if (ngx_ssl_create(plcf->upstream.ssl, plcf->ssl_protocols, NULL)
!= NGX_OK)
{
return NGX_ERROR;
}
cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) {
ngx_ssl_cleanup_ctx(plcf->upstream.ssl);
return NGX_ERROR;
}
cln->handler = ngx_ssl_cleanup_ctx;
cln->data = plcf->upstream.ssl;
if (ngx_ssl_ciphers(cf, plcf->upstream.ssl, &plcf->ssl_ciphers, 0)
!= NGX_OK)
{
return NGX_ERROR;
}
if (plcf->upstream.ssl_certificate
&& plcf->upstream.ssl_certificate->value.len)
{
if (plcf->upstream.ssl_certificate_key == NULL) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no \"proxy_ssl_certificate_key\" is defined "
"for certificate \"%V\"",
&plcf->upstream.ssl_certificate->value);
return NGX_ERROR;
}
if (plcf->upstream.ssl_certificate->lengths
|| plcf->upstream.ssl_certificate_key->lengths)
{
plcf->upstream.ssl_passwords =
ngx_ssl_preserve_passwords(cf, plcf->upstream.ssl_passwords);
if (plcf->upstream.ssl_passwords == NULL) {
return NGX_ERROR;
}
} else {
if (ngx_ssl_certificate(cf, plcf->upstream.ssl,
&plcf->upstream.ssl_certificate->value,
&plcf->upstream.ssl_certificate_key->value,
plcf->upstream.ssl_passwords)
!= NGX_OK)
{
return NGX_ERROR;
}
}
}
if (plcf->upstream.ssl_verify) {
if (plcf->ssl_trusted_certificate.len == 0) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no proxy_ssl_trusted_certificate for proxy_ssl_verify");
return NGX_ERROR;
}
if (ngx_ssl_trusted_certificate(cf, plcf->upstream.ssl,
&plcf->ssl_trusted_certificate,
plcf->ssl_verify_depth)
!= NGX_OK)
{
return NGX_ERROR;
}
if (ngx_ssl_crl(cf, plcf->upstream.ssl, &plcf->ssl_crl) != NGX_OK) {
return NGX_ERROR;
}
}
if (ngx_ssl_client_session_cache(cf, plcf->upstream.ssl,
plcf->upstream.ssl_session_reuse)
!= NGX_OK)
{
return NGX_ERROR;
}
if (ngx_ssl_conf_commands(cf, plcf->upstream.ssl, plcf->ssl_conf_commands)
!= NGX_OK)
{
return NGX_ERROR;
}
return NGX_OK;
}
#endif
static void
ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v)
{ … }