--[[ @object-name: vpn-policy @object-desc: vpn策略 --]] local uci = require "uci" local lfactory = require "lfactory" local M = {} local function set_process_user(user) local services = {"gl_mqtt","sysntpd","ddns"} for i=1, #services do -- 1表示不使用VPN if user == 1 then os.execute("[ -z \"$(grep 'group nonevpn' /etc/init.d/" .. services[i] .. ")\" ] && sed -i \"/procd_open_instance/a procd_set_param group nonevpn\" /etc/init.d/" .. services[i]) else os.execute("sed -i \"/procd_set_param group nonevpn/d\" /etc/init.d/" .. services[i]) end os.execute("/etc/init.d/" .. services[i] .. " restart") end end local function load_proxy(mode) os.execute("/usr/bin/apply_killswitch 1") if mode == 3 or mode == 4 or mode == 5 then os.execute("/usr/bin/route_policy " .. mode) os.execute("/etc/openvpn/scripts/ovpnclient-up ovpnclient " .. mode) os.execute("/etc/wireguard/scripts/wgclient-route-update.sh wgclient " .. mode) elseif mode == 0 or mode == 1 or mode == 2 then os.execute("/usr/bin/route_policy " .. 2) os.execute("/etc/openvpn/scripts/ovpnclient-up ovpnclient " .. mode) os.execute("/etc/wireguard/scripts/wgclient-route-update.sh wgclient " .. mode) end end --[[ @method-type: call @method-name: get_global_policy @method-desc: 获取全局策略 @out number kill_switch 是否拦截未经VPN的流量(0:禁用killswitch,不拦截任何流量,1:在任何情况下拦截不经VPN的流量,2:仅在VPN客户端启用时拦截未经VPN的流量) @out number wan_access 在VPN使能时,是否允许LAN->WAN的转发数据(0:不允许,1:允许) @out number service_policy 是否对路由器上glinet的服务使用VPN(0:跟随系统设置 1:不使用VPN) @out number vpn_server_policy VPN服务器数据策略(0:跟随 vpn client 网络 1:通过WAN网络) @out number ?err_code 错误码 @out string ?err_msg 错误信息 @in-example: {"jsonrpc":"2.0","id":1,"method":"call","params":["","vpn-policy","get_global_policy",{}]} @out-example: {"jsonrpc": "2.0", "id": 1, "result": {"kill_switch":0,"wan_access":0,"service_policy":1}} --]] function M.get_global_policy(params) local ret = {} local c = uci.cursor() ret["kill_switch"] = tonumber(c:get("vpnpolicy", "global", "kill_switch") or "0") ret["wan_access"] = tonumber(c:get("vpnpolicy", "global", "wan_access") or "0") ret["service_policy"] = tonumber(c:get("vpnpolicy", "global", "service_policy") or "0") ret["vpn_server_policy"] = tonumber(c:get("vpnpolicy", "global", "vpn_server_policy") or "0") return ret end --[[ @method-type: call @method-name: set_global_policy @method-desc: 设置全局策略 @in number ?kill_switch 是否拦截未经VPN的流量(0:禁用killswitch,不拦截任何流量,1:在任何情况下拦截不经VPN的流量) @in number ?wan_access 在VPN使能时,是否允许LAN->WAN的转发数据(0:不允许,1:允许) @in number ?service_policy 是否对路由器上glinet的服务使用VPN(0:跟随系统设置 1:不使用VPN) @in number ?vpn_server_policy VPN服务器数据策略(0:跟随 vpn client 网络 1:通过WAN网络) @out number ?err_code 错误码(-1: 缺少必须参数) @out string ?err_msg 错误信息 @in-example: {"jsonrpc":"2.0","id":1,"method":"call","params":["","vpn-policy","set_global_policy",{"kill_switch":0,"wan_access":0,"service_policy":1,"vpn_server_policy":1}]} @out-example: {"jsonrpc": "2.0", "id": 1, "result": {}} --]] function M.set_global_policy(params) if params.kill_switch == nil and params.wan_access == nil and params.service_policy == nil and params.vpn_server_policy == nil then return { err_code = -1, err_msg = "parameter missing" } end local c = uci.cursor() c:set("vpnpolicy", "global", "policy") if params.kill_switch ~= nil then c:set("vpnpolicy", "global", "kill_switch", params.kill_switch) end if params.wan_access ~= nil then c:set("vpnpolicy", "global", "wan_access", params.wan_access) end if params.service_policy ~= nil then c:set("vpnpolicy", "global", "service_policy", params.service_policy) end if params.vpn_server_policy ~= nil then c:set("vpnpolicy", "global", "vpn_server_policy", params.vpn_server_policy) end c:commit("vpnpolicy") if params.vpn_server_policy ~= nil then local item=c:get("firewall", "vpn_server_policy"); if item == nil then c:set("firewall", "vpn_server_policy", "include") c:set("firewall", "vpn_server_policy", "type", "script") c:set("firewall", "vpn_server_policy", "path", "/etc/firewall.vpn_server_policy.sh") c:set("firewall", "vpn_server_policy", "reload", "1") c:set("firewall", "vpn_server_policy", "enabled", "1") c:commit("firewall"); end if params.vpn_server_policy == 1 then -- vpn server to wan c:set("firewall", "wgserver2wgclient", "enabled", "0") c:set("firewall", "wgserver2ovpnclient", "enabled", "0") c:set("firewall", "ovpnserver2ovpnclient", "enabled", "0") c:set("firewall", "ovpnserver2wgclient", "enabled", "0") c:commit("firewall"); else -- vpn server to vpn client c:set("firewall", "wgserver2wgclient", "enabled", "1") c:set("firewall", "wgserver2ovpnclient", "enabled", "1") c:set("firewall", "ovpnserver2ovpnclient", "enabled", "1") c:set("firewall", "ovpnserver2wgclient", "enabled", "1") c:commit("firewall"); end end os.execute("cat /etc/group|grep -q nonevpn || echo nonevpn:x:65533:root >>/etc/group") if params.service_policy == 0 then set_process_user(0) else set_process_user(1) end -- 手动调用API,立即更新killswitch相关配置 ngx.timer.at(1, function() os.execute("/usr/bin/apply_killswitch 1 2>/dev/null") os.execute("/usr/bin/route_policy update") end) end --[[ @method-type: call @method-name: set_proxy_mode @method-desc: 设置VPN代理模式 @in number mode 代理模式(0:全局代理,1:自动检测路由,2:自定义路由,3:基于目的站点,4:基于客户端设备,5:基于VLAN) @out number ?err_code 错误码(-1: 缺少参数) @out string ?err_msg 错误信息 @in-example: {"jsonrpc":"2.0","id":1,"method":"call","params":["","vpn-policy","set_proxy_mode",{"mode":0}]} @out-example: {"jsonrpc": "2.0", "id": 1, "result": {}} --]] function M.set_proxy_mode(params) if params.mode == nil then return { err_code = -1, err_msg = "parameter missing" } end local c = uci.cursor() local mode = params.mode c:set("vpnpolicy", "route_policy", "service") c:set("vpnpolicy", "route_policy", "proxy_mode", mode) c:commit("vpnpolicy") load_proxy(mode) end --[[ @method-type: call @method-name: get_proxy_mode @method-desc: 获取VPN代理模式 @out number mode 代理模式(0:全局代理,1:自动检测路由,2:自定义路由,3:基于目的站点,4:基于客户端设备,5:基于VLAN) @out number ?err_code 错误码 @out string ?err_msg 错误信息 @in-example: {"jsonrpc":"2.0","id":1,"method":"call","params":["","vpn-policy","get_proxy_mode",{}]} @out-example: {"jsonrpc": "2.0", "id": 1, "result": {"mode":0}} --]] function M.get_proxy_mode(params) local ret = {} local c = uci.cursor() local mode = c:get("vpnpolicy", "route_policy", "proxy_mode") or 0 ret["mode"] = tonumber(mode) return ret end --[[ @method-type: call @method-name: set_domain_policy @method-desc: 设置domain策略 @in number default_policy 默认策略(0:不使用vpn,1:使用vpn) @in array domain_list 例外的域名/IP列表 @out number ?err_code 错误码(-1: 缺少参数) @out string ?err_msg 错误信息 @in-example: {"jsonrpc":"2.0","id":1,"method":"call","params":["","vpn-policy","set_domain_policy",{"default_policy":0,"domain_list":["google.com","facebook.com"]}]} @out-example: {"jsonrpc": "2.0", "id": 1, "result": {}} --]] function M.set_domain_policy(params) if params.default_policy == nil then return { err_code = 1, err_msg = "parameter missing" } end local c = uci.cursor() c:set("vpnpolicy", "domain", "policy") c:set("vpnpolicy", "domain", "default_policy", params.default_policy) if params.domain_list ~= nil then if #params.domain_list ~= 0 then c:set("vpnpolicy", "domain", "domain", params.domain_list) else c:delete("vpnpolicy", "domain", "domain") end end c:commit("vpnpolicy") os.execute("/usr/bin/route_policy " .. 3) end --[[ @method-type: call @method-name: get_domain_policy @method-desc: 获取domain策略 @out number default_policy 默认策略(0:不使用vpn,1:使用vpn) @out string domain_list 例外的域名/IP列表 @out number ?err_code 错误码 @out string ?err_msg 错误信息 @in-example: {"jsonrpc":"2.0","id":1,"method":"call","params":["","vpn-policy","get_domain_policy",{}]} @out-example: {"jsonrpc": "2.0", "id": 1, "result": {"default_policy":0,"domain_list":["google.com","facebook.com"]}} --]] function M.get_domain_policy(params) local c = uci.cursor() local ret = {} ret["default_policy"] = tonumber(c:get("vpnpolicy", "domain", "default_policy") or 1) local domain_list = c:get("vpnpolicy", "domain", "domain") ret["domain_list"] = domain_list return ret end --[[ @method-type: call @method-name: set_mac_policy @method-desc: 设置mac策略 @in number default_policy 默认策略(0:不使用vpn,1:使用vpn) @in array mac_list 例外的mac列表 @out number ?err_code 错误码(-1: 缺少参数) @out string ?err_msg 错误信息 @in-example: {"jsonrpc":"2.0","id":1,"method":"call","params":["","vpn-policy","set_mac_policy",{"default_policy":0,"mac_list":["94:83:C4:0E:10:DF","94:83:C4:0E:20:DF"]}]} @out-example: {"jsonrpc": "2.0", "id": 1, "result": {}} --]] function M.set_mac_policy(params) if params.default_policy == nil then return { err_code = 1, err_msg = "parameter missing" } end local c = uci.cursor() c:set("vpnpolicy", "mac", "policy") c:set("vpnpolicy", "mac", "default_policy", params.default_policy) if params.mac_list ~= nil then if #params.mac_list ~= 0 then c:set("vpnpolicy", "mac", "mac", params.mac_list) else c:delete("vpnpolicy", "mac", "mac") end end c:commit("vpnpolicy") os.execute("/usr/bin/route_policy " .. 4) end --[[ @method-type: call @method-name: get_mac_policy @method-desc: 获取mac策略 @out number default_policy 默认策略(0:不使用vpn,1:使用vpn) @out array mac_list 例外的mac列表 @out number ?err_code 错误码 @out string ?err_msg 错误信息 @in-example: {"jsonrpc":"2.0","id":1,"method":"call","params":["","vpn-policy","get_mac_policy",{}]} @out-example: {"jsonrpc": "2.0", "id": 1, "result": {"default_policy":0,"mac_list":["94:83:C4:0E:10:DF","94:83:C4:0E:20:DF"]}} --]] function M.get_mac_policy(params) local c = uci.cursor() local ret = {} local array = {} ret["default_policy"] = tonumber(c:get("vpnpolicy", "mac", "default_policy") or 1) local mac_list = c:get("vpnpolicy", "mac", "mac") if mac_list ~= nil then for _, value in pairs(mac_list) do table.insert(array, value) end end ret["mac_list"] = array return ret end --[[ @method-type: call @method-name: set_vlan_policy @method-desc: 设置vlan策略 @in array vlans vlan信息 @in number ?vlans.id vlan id(1:private, 2:guest) @in number ?vlans.vpn vlan是否使用vpn(0:禁用,1:使能) @out number ?err_code 错误码(-1: 缺少参数) @out string ?err_msg 错误信息 @in-example: {"jsonrpc":"2.0","id":1,"method":"call","params":["","vpn-policy","set_vlan_policy",{"vlans":[{"id":1,"vpn":0},{"id":2,"vpn":0}]}]} @out-example: {"jsonrpc": "2.0", "id": 1, "result": {}} --]] function M.set_vlan_policy(params) local c = uci.cursor() if params.vlans ~= nil and #params.vlans then for i = 1, #params.vlans do if i == 1 then c:set("vpnpolicy", "vlan", "policy") end if params.vlans[i].id == 1 then c:set("vpnpolicy", "vlan", "private", params.vlans[i].vpn) end if params.vlans[i].id == 2 then c:set("vpnpolicy", "vlan", "guest", params.vlans[i].vpn) end end end c:commit("vpnpolicy") os.execute("/usr/bin/route_policy " .. 5) end --[[ @method-type: call @method-name: get_vlan_policy @method-desc: 获取vlan策略 @out array vlans vlan信息 @out number ?vlans.id vlan id(1:private, 2:guest) @out number ?vlans.vpn vlan是否使用vpn(0:禁用,1:使能) @out number ?err_code 错误码 @out string ?err_msg 错误信息 @in-example: {"jsonrpc":"2.0","id":1,"method":"call","params":["","vpn-policy","get_vlan_policy",{}]} @out-example: {"jsonrpc": "2.0", "id": 1, "result": {"vlans":[{"id":1,"vpn":0},{"id":2,"vpn":0}]}} --]] function M.get_vlan_policy(params) local ret = {} local array = {} local c = uci.cursor() local vlan_list = c:get_all("vpnpolicy", "vlan") if vlan_list ~= nil then for key, value in pairs(vlan_list) do if string.sub(key, 1, 1) ~= "." then if key == "private" then table.insert(array, {["id"] = 1, ["vpn"] = tonumber(value)}) end if key == "guest" and lfactory.get_radio() then table.insert(array, {["id"] = 2, ["vpn"] = tonumber(value)}) end end end end ret["vlans"] = array return ret end return M