Nginx采用主-从(master-worker)进程模型: - 主进程(master):负责读取配置、管理工作进程 - 工作进程(worker):实际处理请求的进程
默认情况下,所有worker进程共享相同的配置和资源,要实现隔离需要修改Nginx的进程模型。
修改src/os/unix/ngx_process_cycle.c
文件,在worker进程初始化时加入cgroup设置:
static void
ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
{
// ...原有代码...
// 新增cgroup隔离
if (ngx_set_cgroup(cycle, worker) != NGX_OK) {
exit(2);
}
// ...后续代码...
}
实现ngx_set_cgroup
函数,将不同worker分配到不同cgroup中。
修改src/os/unix/ngx_process.c
中的ngx_setaffinity
函数:
ngx_int_t
ngx_setaffinity(ngx_cpuset_t *cpu_affinity, ngx_log_t *log)
{
// 根据worker编号分配不同的CPU核心
ngx_int_t worker_num = ngx_processes[ngx_process_slot].worker_num;
CPU_ZERO(cpu_affinity);
CPU_SET(worker_num % CPU_SETSIZE, cpu_affinity);
// 原有设置代码...
}
更彻底的隔离可以通过Linux命名空间实现,需要修改worker进程启动代码:
static void
ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
{
// 创建新的命名空间
if (unshare(CLONE_NEWNET | CLONE_NEWIPC | CLONE_NEWPID) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"unshare() failed");
exit(2);
}
// ...原有初始化代码...
}
在src/core/ngx_cycle.c
中修改内存分配策略:
ngx_cycle_t *
ngx_init_cycle(ngx_cycle_t *old_cycle)
{
// 为每个worker分配独立的内存池
new_cycle->worker_mem_pool = ngx_create_pool(ngx_pagesize, new_cycle->log);
// ...其他初始化代码...
}
修改src/os/unix/ngx_process_cycle.c
:
static void
ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
{
// 关闭从master继承的不必要文件描述符
for (fd = 3; fd < 1024; fd++) {
if (fd != cycle->listening[i].fd) {
close(fd);
}
}
}
实现独立的网络栈:
static void
ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
{
// 创建独立的网络命名空间
if (unshare(CLONE_NEWNET) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"unshare(CLONE_NEWNET) failed");
exit(2);
}
// 重新初始化网络接口
ngx_network_init(cycle);
}
在src/os/unix/ngx_process_cycle.c
中:
static void
ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
{
// 删除不必要的capabilities
struct __user_cap_header_struct hdr;
struct __user_cap_data_struct data;
capget(&hdr, &data);
data.effective &= ~(CAP_DAC_OVERRIDE | CAP_NET_ADMIN);
capset(&hdr, &data);
}
添加seccomp限制:
static void
ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
{
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(reboot), 0);
// 添加其他限制规则...
seccomp_load(ctx);
seccomp_release(ctx);
}
需要扩展Nginx配置系统以支持隔离参数:
src/core/ngx_conf_file.h
中添加新指令定义src/core/ngx_conf_file.c
中实现配置解析src/core/ngx_cycle.c
应用隔离配置/proc/[pid]/status
中的命名空间和cgroup信息strace
观察系统调用限制通过以上源码级别的修改,可以实现Nginx worker进程的多层次隔离,提高安全性和稳定性。实际实现时需要根据具体需求选择合适的隔离层级和范围。