mirror of
https://github.com/nginx/nginx.git
synced 2026-05-13 17:46:53 +00:00
Retain CAP_NET_RAW capability for transparent proxying.
The capability is retained automatically in unprivileged worker processes after changing UID if transparent proxying is enabled at least once in nginx configuration. The feature is only available in Linux.
This commit is contained in:
parent
d2d737e70b
commit
752f66bf7d
6 changed files with 82 additions and 0 deletions
|
|
@ -157,6 +157,37 @@ ngx_feature_test="if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) return 1"
|
|||
. auto/feature
|
||||
|
||||
|
||||
# prctl(PR_SET_KEEPCAPS)
|
||||
|
||||
ngx_feature="prctl(PR_SET_KEEPCAPS)"
|
||||
ngx_feature_name="NGX_HAVE_PR_SET_KEEPCAPS"
|
||||
ngx_feature_run=yes
|
||||
ngx_feature_incs="#include <sys/prctl.h>"
|
||||
ngx_feature_path=
|
||||
ngx_feature_libs=
|
||||
ngx_feature_test="if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) return 1"
|
||||
. auto/feature
|
||||
|
||||
|
||||
# capabilities
|
||||
|
||||
ngx_feature="capabilities"
|
||||
ngx_feature_name="NGX_HAVE_CAPABILITIES"
|
||||
ngx_feature_run=no
|
||||
ngx_feature_incs="#include <sys/capability.h>"
|
||||
ngx_feature_path=
|
||||
ngx_feature_libs=
|
||||
ngx_feature_test="struct __user_cap_data_struct data;
|
||||
struct __user_cap_header_struct header;
|
||||
|
||||
header.version = _LINUX_CAPABILITY_VERSION_3;
|
||||
data.effective = CAP_TO_MASK(CAP_NET_RAW);
|
||||
data.permitted = 0;
|
||||
|
||||
(void) capset(&header, &data)"
|
||||
. auto/feature
|
||||
|
||||
|
||||
# crypt_r()
|
||||
|
||||
ngx_feature="crypt_r()"
|
||||
|
|
|
|||
|
|
@ -114,6 +114,8 @@ typedef struct {
|
|||
|
||||
ngx_array_t env;
|
||||
char **environment;
|
||||
|
||||
ngx_uint_t transparent; /* unsigned transparent:1; */
|
||||
} ngx_core_conf_t;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6078,6 +6078,12 @@ ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||
if (cf->args->nelts > 2) {
|
||||
if (ngx_strcmp(value[2].data, "transparent") == 0) {
|
||||
#if (NGX_HAVE_TRANSPARENT_PROXY)
|
||||
ngx_core_conf_t *ccf;
|
||||
|
||||
ccf = (ngx_core_conf_t *) ngx_get_conf(cf->cycle->conf_ctx,
|
||||
ngx_core_module);
|
||||
|
||||
ccf->transparent = 1;
|
||||
local->transparent = 1;
|
||||
#else
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
|
|
|
|||
|
|
@ -99,6 +99,11 @@ typedef struct iocb ngx_aiocb_t;
|
|||
#endif
|
||||
|
||||
|
||||
#if (NGX_HAVE_CAPABILITIES)
|
||||
#include <sys/capability.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define NGX_LISTEN_BACKLOG 511
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -839,12 +839,44 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
|
|||
ccf->username, ccf->group);
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_PR_SET_KEEPCAPS && NGX_HAVE_CAPABILITIES)
|
||||
if (ccf->transparent && ccf->user) {
|
||||
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
|
||||
"prctl(PR_SET_KEEPCAPS, 1) failed");
|
||||
/* fatal */
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (setuid(ccf->user) == -1) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
|
||||
"setuid(%d) failed", ccf->user);
|
||||
/* fatal */
|
||||
exit(2);
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_CAPABILITIES)
|
||||
if (ccf->transparent && ccf->user) {
|
||||
struct __user_cap_data_struct data;
|
||||
struct __user_cap_header_struct header;
|
||||
|
||||
ngx_memzero(&header, sizeof(struct __user_cap_header_struct));
|
||||
ngx_memzero(&data, sizeof(struct __user_cap_data_struct));
|
||||
|
||||
header.version = _LINUX_CAPABILITY_VERSION_3;
|
||||
data.effective = CAP_TO_MASK(CAP_NET_RAW);
|
||||
data.permitted = data.effective;
|
||||
|
||||
if (capset(&header, &data) == -1) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
|
||||
"capset() failed");
|
||||
/* fatal */
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (worker >= 0) {
|
||||
|
|
|
|||
|
|
@ -2155,6 +2155,12 @@ ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
if (cf->args->nelts > 2) {
|
||||
if (ngx_strcmp(value[2].data, "transparent") == 0) {
|
||||
#if (NGX_HAVE_TRANSPARENT_PROXY)
|
||||
ngx_core_conf_t *ccf;
|
||||
|
||||
ccf = (ngx_core_conf_t *) ngx_get_conf(cf->cycle->conf_ctx,
|
||||
ngx_core_module);
|
||||
|
||||
ccf->transparent = 1;
|
||||
local->transparent = 1;
|
||||
#else
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue