目录

使用OpenResty reload ipsec服务

背景介绍

  • Debian 11
  • OpenResty 1.19.9.1

默认情况下,Nginx/OpenResty会启动一个root权限运行的master进程,之后再用指定的普通用户权限启动对应的worker,因要root权限才能操作ipsec服务,为了解决普通worker的提权问题,OpenResty提供了一个privileged agent来对这些提权操作进行处理,本文就是利用privileged agent来实现ipsec服务的重启操作。

基本思路

在OpenResty的 init_by_lua_block 阶段启动privileged agent,之后在 init_worker_by_lua_block 阶段针对privileged agent设置其具体需要执行的操作,最终在 content_by_lua_block 中通过改变共享内存的 lua_shared_dict 字段的内容触发对应的reload操作。

对应配置

root@debian:~# cat /etc/openresty/nginx.conf
...
user app; #普通用户启动worker
...
http {
    ...
    lua_shared_dict reload_status 1m; #共享内存dict

	init_by_lua_block {
	    local process = require "ngx.process"
	
	    -- enables privileged agent process
	    local ok, err = process.enable_privileged_agent()
	    if not ok then
	        ngx.log(ngx.ERR, "enables privileged agent failed error:", err)
	    end
	
	    -- output process type
	    ngx.log(ngx.INFO, "process type: ", process.type())
	}
	
	init_worker_by_lua_block {
	    local process = require "ngx.process"
	    local shell = require "resty.shell"
	
	    local timeout = 3000  -- ms
	    local max_size = 4096  -- byte
	
	    local function ipsec_reload(premature)
	        local reload_status = ngx.shared.reload_status
	        local value, flags = reload_status:get("ipsec")
	        if value == 1 then
	            ngx.log(ngx.ALERT, "ipsec reloading ")
	            local shell_cmd = "/usr/sbin/ipsec reload"
	            local ok, stdout, stderr, reason, status = shell.run(shell_cmd, nil, timeout, max_size)
	            local value, flags = reload_status:set("ipsec",0)
	        end
	    end
	
	    if process.type() == "privileged agent" then
	        local ok, err = ngx.timer.every(60, ipsec_reload)
	        if not ok then
	            ngx.log(ngx.ERR, "ipsec info: ", err)
	        end
	    end
	}

    server {
        listen 80;
        server_name t.test.com;

    	location /t {
    		#如果是生产环境,需要加上IP白名单或mTLS认证来提高安全性
    	    content_by_lua_block {
    	        local reload_s = ngx.shared.reload_status
    	        reload_s:set("ipsec", 1)
    	        ngx.say("reload sucessful")
    	    }
    	}
	}

总结

通过上面的操作可以很方便的给OpenResty进行扩展执行任何root权限执行的功能,可以作为运维维护的辅助利器,但切记做好安全防护哟。