local api = require "luci.passwall.api" local sys = api.sys local fs = api.fs local datatypes = api.datatypes local TMP = {} local function tinsert(table_name, val) if table_name and type(table_name) == "table" then if not TMP[table_name] then TMP[table_name] = {} end if TMP[table_name][val] then return false end table.insert(table_name, val) TMP[table_name][val] = true return true end return false end local function backup_servers() local DNSMASQ_DNS = api.uci_get("dhcp", "@dnsmasq[0]", "server") if DNSMASQ_DNS and #DNSMASQ_DNS > 0 then api.uci_set_c("@global[0]", "dnsmasq_servers", DNSMASQ_DNS) api.uci_save_c(true) end end local function restore_servers() local dns_table = {} local DNSMASQ_DNS = api.uci_get("dhcp", "@dnsmasq[0]", "server") if DNSMASQ_DNS and #DNSMASQ_DNS > 0 then for k, v in ipairs(DNSMASQ_DNS) do tinsert(dns_table, v) end end local OLD_SERVER = api.uci_get(api.c_config, "@global[0]", "dnsmasq_servers") if OLD_SERVER and #OLD_SERVER > 0 then for k, v in ipairs(OLD_SERVER) do tinsert(dns_table, v) end api.uci_del_c("@global[0]", "dnsmasq_servers") api.uci_save_c(true) end if dns_table and #dns_table > 0 then api.uci_set("dhcp", "@dnsmasq[0]", "server", dns_table) api.uci_save(nil, "dhcp", true) end end function stretch() local dnsmasq_server = api.uci_get("dhcp", "@dnsmasq[0]", "server") local dnsmasq_noresolv = api.uci_get("dhcp", "@dnsmasq[0]", "noresolv") local _flag if dnsmasq_server and #dnsmasq_server > 0 then for k, v in ipairs(dnsmasq_server) do if not v:find("/") then _flag = true end end end if not _flag and dnsmasq_noresolv == "1" then api.uci_del("dhcp", "@dnsmasq[0]", "noresolv") local RESOLVFILE = "/tmp/resolv.conf.d/resolv.conf.auto" if (fs.stat(RESOLVFILE, "size") or 0) == 0 then RESOLVFILE = "/tmp/resolv.conf.auto" end api.uci_set("dhcp", "@dnsmasq[0]", "resolvfile", RESOLVFILE) api.uci_save(nil, "dhcp", true) end end function restart(var) local LOG = var["-LOG"] sys.call("/etc/init.d/dnsmasq restart >/dev/null 2>&1") if LOG == "1" then api.log("重启 dnsmasq 服务") end end function logic_restart(var) local LOG = var["-LOG"] local DEFAULT_DNS = api.get_cache_var("DEFAULT_DNS") if DEFAULT_DNS then backup_servers() --sys.call("sed -i '/list server/d' /etc/config/dhcp >/dev/null 2>&1") local dns_table = {} local dnsmasq_server = api.uci_get("dhcp", "@dnsmasq[0]", "server") if dnsmasq_server and #dnsmasq_server > 0 then for k, v in ipairs(dnsmasq_server) do if v:find("/") then tinsert(dns_table, v) end end api.uci_set("dhcp", "@dnsmasq[0]", "server", dns_table) api.uci_save(nil, "dhcp", true) end sys.call("/etc/init.d/dnsmasq restart >/dev/null 2>&1") restore_servers() else sys.call("/etc/init.d/dnsmasq restart >/dev/null 2>&1") end if LOG == "1" then api.log("重启 dnsmasq 服务") end end function copy_instance(var) local LISTEN_PORT = var["-LISTEN_PORT"] local TMP_DNSMASQ_PATH = var["-TMP_DNSMASQ_PATH"] local conf_lines = {} local DEFAULT_DNSMASQ_CFGID = sys.exec("echo -n $(uci -q show dhcp.@dnsmasq[0] | awk 'NR==1 {split($0, conf, /[.=]/); print conf[2]}')") local conf_file = "/var/etc/dnsmasq.conf." .. DEFAULT_DNSMASQ_CFGID local retry = 5 while not fs.access(conf_file) and retry > 0 do api.nixio.nanosleep(1, 0) retry = retry - 1 end if fs.access(conf_file) then for line in io.lines(conf_file) do local filter if line:find("passwall") then filter = true end if line:find("ubus") then filter = true end if line:find("dhcp") then filter = true end if line:find("server=") == 1 then filter = true end if line:find("port=") == 1 then filter = true end if line:find("min%-cache%-ttl") == 1 then filter = true end if line:find("conf%-dir=") == 1 then filter = true if TMP_DNSMASQ_PATH then local tmp_path = line:sub(1 + #"conf-dir=") sys.call(string.format("cp -r %s/* %s/ 2>/dev/null", tmp_path, TMP_DNSMASQ_PATH)) end end if line:find("address=") == 1 or (line:find("server=") == 1 and line:find("/")) then filter = nil end if not filter then tinsert(conf_lines, line) end end else sys.call("logger -t passwall 'ERROR: dnsmasq config " .. conf_file .. " not found after 5s wait! DNS hijacking will fail.'") end tinsert(conf_lines, "port=" .. LISTEN_PORT) if TMP_DNSMASQ_PATH then api.remove(TMP_DNSMASQ_PATH .. "/*passwall*") end if var["-return"] == "1" then return conf_lines end if #conf_lines > 0 then local DNSMASQ_CONF = var["-DNSMASQ_CONF"] local conf_out = io.open(DNSMASQ_CONF, "a") conf_out:write(table.concat(conf_lines, "\n")) conf_out:write("\n") conf_out:close() end end function add_rule(var) local FLAG = var["-FLAG"] local TMP_DNSMASQ_PATH = var["-TMP_DNSMASQ_PATH"] local DNSMASQ_CONF_FILE = var["-DNSMASQ_CONF_FILE"] local LISTEN_PORT = var["-LISTEN_PORT"] local DEFAULT_DNS = var["-DEFAULT_DNS"] local LOCAL_DNS = var["-LOCAL_DNS"] local TUN_DNS = var["-TUN_DNS"] local USE_DEFAULT_DNS = var["-USE_DEFAULT_DNS"] local CHINADNS_DNS = var["-CHINADNS_DNS"] local NODE = var["-NODE"] local USE_DIRECT_LIST = var["-USE_DIRECT_LIST"] local USE_PROXY_LIST = var["-USE_PROXY_LIST"] local USE_BLOCK_LIST = var["-USE_BLOCK_LIST"] local USE_GFW_LIST = var["-USE_GFW_LIST"] local CHN_LIST = var["-CHN_LIST"] local DEFAULT_PROXY_MODE = var["-DEFAULT_PROXY_MODE"] local NO_PROXY_IPV6 = var["-NO_PROXY_IPV6"] local NO_LOGIC_LOG = var["-NO_LOGIC_LOG"] local NFTFLAG = var["-NFTFLAG"] local CACHE_PATH = api.CACHE_PATH local CACHE_FLAG = "dnsmasq_" .. FLAG local CACHE_DNS_PATH = CACHE_PATH .. "/" .. CACHE_FLAG local CACHE_TEXT_FILE = CACHE_DNS_PATH .. ".txt" local USE_CHINADNS_NG = "0" local IS_SHUNT_NODE = api.uci_get_c(NODE, "protocol") == "_shunt" local USE_GEOVIEW = api.uci_get_c("@global_rules[0]", "enable_geoview") local list1 = {} local excluded_domain = {} if not api.is_finded("geoview") then USE_GEOVIEW = "0" end local function log(...) if NO_LOGIC_LOG == "1" then return end api.log(...) end local function check_dns(domain, dns) if domain == "" or domain:find("#") then return false end if not dns then return end for k,v in ipairs(list1[domain].dns) do if dns == v then return true end end return false end local function check_ipset(domain, ipset) if domain == "" or domain:find("#") then return false end if not ipset then return end for k,v in ipairs(list1[domain].ipsets) do if ipset == v then return true end end return false end local function set_domain_address(domain, address) if domain == "" or domain:find("#") then return end if not list1[domain] then list1[domain] = { dns = {}, ipsets = {} } end if not list1[domain].address then list1[domain].address = address end end local function set_domain_dns(domain, dns) if domain == "" or domain:find("#") then return end if not dns then return end if not list1[domain] then list1[domain] = { dns = {}, ipsets = {} } end for line in string.gmatch(dns, '[^' .. "," .. ']+') do if not check_dns(domain, line) then table.insert(list1[domain].dns, line) end end end local function set_domain_ipset(domain, ipset) if domain == "" or domain:find("#") then return end if not ipset then return end if not list1[domain] then list1[domain] = { dns = {}, ipsets = {} } end for line in string.gmatch(ipset, '[^' .. "," .. ']+') do if not check_ipset(domain, line) then table.insert(list1[domain].ipsets, line) end end end local function add_excluded_domain(domain) if domain == "" or domain:find("#") then return end excluded_domain[domain] = true end local function check_excluded_domain(domain) if domain == "" or domain:find("#") then return false end if excluded_domain[domain] then return true end local pos = domain:find(".", 1, true) while pos do if excluded_domain[domain:sub(pos + 1)] then return true end pos = domain:find(".", pos + 1, true) end return false end local function foreach_geosite(list_arg, callback) local geosite_path = api.uci_get_c("@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/" geosite_path = geosite_path:match("^(.*)/") .. "/geosite.dat" if not fs.access(geosite_path) then return 1, "File geosite.dat not found" end if not list_arg or list_arg == "" then return 1, "Site list cannot be empty" end local bin = api.finded_com("geoview") local cmd = string.format("%q -type geosite -action extract -input %q -list %q -lowmem=true", bin, geosite_path, list_arg) local code, out = api.exec_call(cmd) if code ~= 0 then return code, out end for line in out:gmatch("[^\r\n]+") do callback(line) end return 0 end local function get_dns_config_key() local address_md5 = api.md5_string(sys.exec([[uci show passwall | grep -E '\.(address|download_address)=' | cut -d "'" -f 2 | sort -u]])) local new_rules = sys.exec([[ for f in \ /usr/share/passwall/rules/chnlist \ /usr/share/passwall/rules/gfwlist \ /etc/passwall/rules/direct_host \ /etc/passwall/rules/proxy_host \ /etc/passwall/rules/block_host do [ -f "$f" ] && md5sum "$f" | awk '{printf "%s", $1}' done ]]) local SHUNT_LIST = "" if IS_SHUNT_NODE then local t = api.uci_get_c(NODE) api.uci_foreach_c("shunt_rules", function(s) local _node_id = t[s[".name"]] if _node_id and t["shunt_group"] == s.group then SHUNT_LIST = SHUNT_LIST .. (s.domain_list or "") .. (_node_id:sub(1, 1) == "_" and "not-node" or "node") end end) end new_rules = new_rules .. api.md5_string(SHUNT_LIST) return TMP_DNSMASQ_PATH .. DNSMASQ_CONF_FILE .. DEFAULT_DNS .. LOCAL_DNS .. TUN_DNS .. USE_DEFAULT_DNS .. CHINADNS_DNS .. USE_DIRECT_LIST .. USE_PROXY_LIST .. USE_BLOCK_LIST .. USE_GFW_LIST .. CHN_LIST .. DEFAULT_PROXY_MODE .. NO_PROXY_IPV6 .. address_md5 .. new_rules .. NFTFLAG end local dnsmasq_default_dns if USE_DEFAULT_DNS ~= "nil" then if USE_DEFAULT_DNS == "direct" then dnsmasq_default_dns = LOCAL_DNS end if USE_DEFAULT_DNS == "remote" then dnsmasq_default_dns = TUN_DNS end if USE_DEFAULT_DNS == "remote" and CHN_LIST == "direct" then dnsmasq_default_dns = TUN_DNS end end local only_global if DEFAULT_PROXY_MODE == "proxy" and CHN_LIST == "0" and USE_GFW_LIST == "0" then --没有启用中国列表和GFW列表时 dnsmasq_default_dns = TUN_DNS only_global = 1 end if USE_DEFAULT_DNS == "chinadns_ng" and CHINADNS_DNS ~= "0" then dnsmasq_default_dns = CHINADNS_DNS USE_CHINADNS_NG = "1" end local setflag_4= (NFTFLAG == "1") and "4#inet#passwall#" or "" local setflag_6= (NFTFLAG == "1") and "6#inet#passwall#" or "" local new_text = "" if USE_CHINADNS_NG == "0" then local cache_text = "" if fs.access(CACHE_TEXT_FILE) then for line in io.lines(CACHE_TEXT_FILE) do cache_text = line end end new_text = get_dns_config_key() if cache_text == "" or new_text == "" or cache_text ~= new_text then api.remove(CACHE_DNS_PATH .. "*") end else api.remove(CACHE_DNS_PATH .. "*") end if not fs.access(CACHE_DNS_PATH) then fs.mkdir(CACHE_DNS_PATH) local GEO_SUCCESS = true --屏蔽列表 if USE_CHINADNS_NG == "0" and USE_BLOCK_LIST == "1" then local geosite_arg = "" local f = io.open("/etc/passwall/rules/block_host") if f then for line in f:lines() do if not line:find("#") and line:find("geosite:") then line = string.match(line, ":([^:]+)$") geosite_arg = geosite_arg .. (geosite_arg ~= "" and "," or "") .. line else line = api.get_std_domain(line) if line ~= "" and not line:find("#") and not line:find(":") then set_domain_address(line, "") end end end f:close() end if USE_GEOVIEW == "1" and geosite_arg ~= "" then local code, out = foreach_geosite(geosite_arg, function(line) set_domain_address(line, "") end) if code == 0 then log(" - 解析[屏蔽列表] Geosite 到屏蔽域名表(blocklist)完成") else log(" - 解析[屏蔽列表] Geosite 到屏蔽域名表(blocklist)失败![" .. out .. "]") GEO_SUCCESS = false end end end local fwd_dns local no_ipv6 --始终用国内DNS解析节点域名 if true then fwd_dns = LOCAL_DNS if USE_CHINADNS_NG == "1" then fwd_dns = nil else local sets = { setflag_4 .. "psw_vps", setflag_6 .. "psw_vps6" } local function process_address(address) address = (address or ""):lower() if api.vps_domain_exclude(address) then return end if datatypes.hostname(address) then set_domain_dns(address, fwd_dns) set_domain_ipset(address, table.concat(sets, ",")) end end api.uci_foreach_c("nodes", function(t) process_address(t.address) process_address(t.download_address) end) log(string.format(" - 节点列表中的域名(vpslist):%s", fwd_dns or "默认")) end end --直连(白名单)列表 if USE_DIRECT_LIST == "1" then fwd_dns = LOCAL_DNS if USE_CHINADNS_NG == "1" then fwd_dns = nil end if fwd_dns then local sets = { setflag_4 .. "psw_white", setflag_6 .. "psw_white6" } --始终用国内DNS解析直连(白名单)列表 local geosite_arg = "" local f = io.open("/etc/passwall/rules/direct_host") if f then for line in f:lines() do if not line:find("#") and line:find("geosite:") then line = string.match(line, ":([^:]+)$") geosite_arg = geosite_arg .. (geosite_arg ~= "" and "," or "") .. line else line = api.get_std_domain(line) if line ~= "" and not line:find("#") and not line:find(":") then add_excluded_domain(line) set_domain_dns(line, fwd_dns) set_domain_ipset(line, table.concat(sets, ",")) end end end f:close() log(string.format(" - 域名白名单(whitelist):%s", fwd_dns or "默认")) end if USE_GEOVIEW == "1" and geosite_arg ~= "" then local code, out = foreach_geosite(geosite_arg, function(line) add_excluded_domain(line) set_domain_dns(line, fwd_dns) set_domain_ipset(line, table.concat(sets, ",")) end) if code == 0 then log(" - 解析[直连列表] Geosite 到域名白名单(whitelist)完成") else log(" - 解析[直连列表] Geosite 到域名白名单(whitelist)失败![" .. out .. "]") GEO_SUCCESS = false end end end end --代理(黑名单)列表 if USE_PROXY_LIST == "1" then fwd_dns = TUN_DNS if USE_CHINADNS_NG == "1" then fwd_dns = nil end if fwd_dns then local set_name = "psw_black" local set6_name = "psw_black6" if FLAG ~= "default" then set_name = "psw_" .. FLAG .. "_black" set6_name = "psw_" .. FLAG .. "_black6" end local sets = { setflag_4 .. set_name } if NO_PROXY_IPV6 ~= "1" then table.insert(sets, setflag_6 .. set6_name) end --始终使用远程DNS解析代理(黑名单)列表 local geosite_arg = "" local f = io.open("/etc/passwall/rules/proxy_host") if f then for line in f:lines() do if not line:find("#") and line:find("geosite:") then line = string.match(line, ":([^:]+)$") geosite_arg = geosite_arg .. (geosite_arg ~= "" and "," or "") .. line else line = api.get_std_domain(line) if line ~= "" and not line:find("#") and not line:find(":") then add_excluded_domain(line) if NO_PROXY_IPV6 == "1" then set_domain_address(line, "::") end set_domain_dns(line, fwd_dns) set_domain_ipset(line, table.concat(sets, ",")) end end end f:close() log(string.format(" - 代理域名表(blacklist):%s", fwd_dns or "默认")) end if USE_GEOVIEW == "1" and geosite_arg ~= "" then local code, out = foreach_geosite(geosite_arg, function(line) add_excluded_domain(line) if NO_PROXY_IPV6 == "1" then set_domain_address(line, "::") end set_domain_dns(line, fwd_dns) set_domain_ipset(line, table.concat(sets, ",")) end) if code == 0 then log(" - 解析[代理列表] Geosite 到代理域名表(blacklist)完成") else log(" - 解析[代理列表] Geosite 到代理域名表(blacklist)失败![" .. out .. "]") GEO_SUCCESS = false end end end end --GFW列表 if USE_GFW_LIST == "1" then fwd_dns = TUN_DNS if USE_CHINADNS_NG == "1" then fwd_dns = nil end if fwd_dns then local set_name = "psw_gfw" local set6_name = "psw_gfw6" if FLAG ~= "default" then set_name = "psw_" .. FLAG .. "_gfw" set6_name = "psw_" .. FLAG .. "_gfw6" end local sets = { setflag_4 .. set_name } if NO_PROXY_IPV6 ~= "1" then table.insert(sets, setflag_6 .. set6_name) end local f = io.open("/usr/share/passwall/rules/gfwlist") if f then for line in f:lines() do if line ~= "" and not line:find("#") and not check_excluded_domain(line) then if NO_PROXY_IPV6 == "1" then set_domain_address(line, "::") end if dnsmasq_default_dns == fwd_dns then fwd_dns = nil else set_domain_dns(line, fwd_dns) end set_domain_ipset(line, table.concat(sets, ",")) end end f:close() log(string.format(" - 防火墙域名表(gfwlist):%s", fwd_dns or "默认")) end end end --中国列表 if CHN_LIST ~= "0" then fwd_dns = nil if CHN_LIST == "direct" then fwd_dns = LOCAL_DNS end if CHN_LIST == "proxy" then fwd_dns = TUN_DNS end if USE_CHINADNS_NG == "1" then fwd_dns = nil end if fwd_dns then local sets = { setflag_4 .. "psw_chn", setflag_6 .. "psw_chn6" } if CHN_LIST == "proxy" then if NO_PROXY_IPV6 == "1" then sets = { setflag_4 .. "psw_chn" } end end local f = io.open("/usr/share/passwall/rules/chnlist") if f then for line in f:lines() do if line ~= "" and not line:find("#") and not check_excluded_domain(line) then if CHN_LIST == "proxy" and NO_PROXY_IPV6 == "1" then set_domain_address(line, "::") end if dnsmasq_default_dns == fwd_dns then fwd_dns = nil else set_domain_dns(line, fwd_dns) end set_domain_ipset(line, table.concat(sets, ",")) end end f:close() log(string.format(" - 中国域名表(chnlist):%s", fwd_dns or "默认")) end end end --分流规则 if IS_SHUNT_NODE and USE_CHINADNS_NG == "0" and only_global ~= 1 then local t = api.uci_get_c(NODE) local default_node_id = t["default_node"] or "_direct" api.uci_foreach_c("shunt_rules", function(s) local _node_id = t[s[".name"]] if _node_id and t["shunt_group"] == s.group then if _node_id == "_default" then _node_id = default_node_id end fwd_dns = TUN_DNS local sets = { setflag_4 .. "psw_shunt", setflag_6 .. "psw_shunt6" } if FLAG ~= "default" then sets = { setflag_4 .. "psw_" .. FLAG .. "_shunt", setflag_6 .. "psw_" .. FLAG .. "_shunt6" } end local domain_list = s.domain_list or "" local geosite_arg = "" for line in string.gmatch(domain_list, "[^\r\n]+") do if line ~= "" and not line:find("#") and not line:find("regexp:") and not line:find("ext:") and not line:find("rule-set:") and not line:find("rs:") then if line:find("geosite:") then line = string.match(line, ":([^:]+)$") geosite_arg = geosite_arg .. (geosite_arg ~= "" and "," or "") .. line else if line:find("domain:") or line:find("full:") then line = string.match(line, ":([^:]+)$") end line = api.get_std_domain(line) add_excluded_domain(line) set_domain_dns(line, fwd_dns) set_domain_ipset(line, table.concat(sets, ",")) end end end if USE_GFW_LIST == "1" and CHN_LIST == "0" and USE_GEOVIEW == "1" and geosite_arg ~= "" then --仅GFW模式解析geosite local code, out = foreach_geosite(geosite_arg, function(line) add_excluded_domain(line) set_domain_dns(line, fwd_dns) set_domain_ipset(line, table.concat(sets, ",")) end) if code == 0 then log(string.format(" - 解析分流规则(%s) Geosite 完成", s.remarks)) else log(string.format(" - 解析分流规则(%s) Geosite 失败![" .. out .. "]", s.remarks)) GEO_SUCCESS = false end end if _node_id ~= "_direct" and _node_id ~= "_blackhole" then log(string.format(" - Sing-Box/Xray分流规则(%s):%s", s.remarks, fwd_dns or "默认")) end end end) elseif only_global == 1 and NO_PROXY_IPV6 == "1" then --节点:固定节点 --代理模式:全局模式 --过滤代理域名 IPv6:启用 --禁止解析所有IPv6记录 list1["#"] = { dns = {}, ipsets = {}, address = "::" } end if list1 and next(list1) then local address_out = io.open(CACHE_DNS_PATH .. "/000-address.conf", "a") local server_out = io.open(CACHE_DNS_PATH .. "/001-server.conf", "a") local ipset_out = io.open(CACHE_DNS_PATH .. "/ipset.conf", "a") local set_name = "ipset" if NFTFLAG == "1" then set_name = "nftset" end for key, value in pairs(list1) do if value.address then local domain = "." .. key if key == "#" then domain = key end address_out:write(string.format("address=/%s/%s", domain, value.address) .. "\n") end if value.dns and #value.dns > 0 then for i, dns in ipairs(value.dns) do server_out:write(string.format("server=/.%s/%s", key, dns) .. "\n") end end if value.ipsets and #value.ipsets > 0 then local ipsets_str = "" for i, ipset in ipairs(value.ipsets) do ipsets_str = ipsets_str .. ipset .. "," end ipsets_str = ipsets_str:sub(1, #ipsets_str - 1) ipset_out:write(string.format("%s=/.%s/%s", set_name, key, ipsets_str) .. "\n") end end address_out:close() server_out:close() ipset_out:close() end if not GEO_SUCCESS then new_text = "" end local f_out = io.open(CACHE_TEXT_FILE, "a") f_out:write(new_text) f_out:close() else log(" - 从缓存加载 Dnsmasq 域名分流规则。") end if USE_CHINADNS_NG == "0" then api.remove(TMP_DNSMASQ_PATH) fs.symlink(CACHE_DNS_PATH, TMP_DNSMASQ_PATH) end if DNSMASQ_CONF_FILE ~= "nil" then local conf_lines = {} if LISTEN_PORT then --Copy dnsmasq instance conf_lines = copy_instance({["-LISTEN_PORT"] = LISTEN_PORT, ["-TMP_DNSMASQ_PATH"] = TMP_DNSMASQ_PATH, ["-return"] = "1"}) --dhcp.leases to hosts local hosts = api.CACHE_PATH .. "/dhcp-hosts" sys.call("touch " .. hosts) tinsert(conf_lines, "addn-hosts=" .. hosts) else --Modify the default dnsmasq service end if USE_CHINADNS_NG == "0" then tinsert(conf_lines, string.format("conf-dir=%s", TMP_DNSMASQ_PATH)) end if dnsmasq_default_dns then for s in string.gmatch(dnsmasq_default_dns, '[^' .. "," .. ']+') do tinsert(conf_lines, string.format("server=%s", s)) end tinsert(conf_lines, "all-servers") tinsert(conf_lines, "no-poll") tinsert(conf_lines, "no-resolv") if USE_CHINADNS_NG == "0" then log(string.format(" - 默认:%s", dnsmasq_default_dns)) end if FLAG == "default" then api.set_cache_var("DEFAULT_DNS", DEFAULT_DNS) end end if #conf_lines > 0 then local conf_out = io.open(DNSMASQ_CONF_FILE, "a") if conf_out then conf_out:write(table.concat(conf_lines, "\n")) conf_out:write("\n") conf_out:close() end end end if USE_CHINADNS_NG == "0" then log(" - PassWall必须依赖于Dnsmasq,如果你自行配置了错误的DNS流程,将会导致域名(直连/代理)分流失效!!!") end end _G.stretch = stretch _G.restart = restart _G.logic_restart = logic_restart _G.copy_instance = copy_instance _G.add_rule = add_rule if arg[1] then local func =_G[arg[1]] if func then func(api.get_function_args(arg)) end end