From 52737683b0ff41232da6ebf1a22ebeb693685ba1 Mon Sep 17 00:00:00 2001 From: ShanStone <31815718+ShanStone@users.noreply.github.com> Date: Sun, 2 Oct 2022 21:22:16 +0800 Subject: [PATCH] luci-app-passwall: server side initial support nftables --- .../model/cbi/passwall/server/api/app.lua | 84 +++++++++++++------ 1 file changed, 58 insertions(+), 26 deletions(-) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua index f31acfdc5..6e68da3d7 100755 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua @@ -15,6 +15,8 @@ local require_dir = "luci.model.cbi.passwall.server.api." local ipt_bin = sys.exec("echo -n $(/usr/share/passwall/iptables.sh get_ipt_bin)") local ip6t_bin = sys.exec("echo -n $(/usr/share/passwall/iptables.sh get_ip6t_bin)") +local nft_flag = sys.exec("command -v fw4") and "1" or "0" + local function log(...) local f, err = io.open(LOG_APP_FILE, "a") if f and err == nil then @@ -47,6 +49,11 @@ end local function gen_include() cmd(string.format("echo '#!/bin/sh' > /tmp/etc/%s.include", CONFIG)) + if nft_flag == "1" then + cmd("echo \"\" > " .. CONFIG_PATH .. "/" .. CONFIG .. ".nft") + local nft_cmd="for chain in $(nft -a list chains |grep -E \"chain PSW-SERVER\" |awk -F ' ' '{print$2}'); do\n nft list chain inet fw4 ${chain} >> " .. CONFIG_PATH .. "/" .. CONFIG .. ".nft\n done" + cmd(nft_cmd) + end local function extract_rules(n, a) local _ipt = ipt_bin if n == "6" then @@ -59,15 +66,21 @@ local function gen_include() end local f, err = io.open("/tmp/etc/" .. CONFIG .. ".include", "a") if f and err == nil then - f:write(ipt_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ipt_bin .. '-restore -c' .. "\n") - f:write(ipt_bin .. '-restore -n <<-EOT' .. "\n") - f:write(extract_rules("4", "filter") .. "\n") - f:write("EOT" .. "\n") - f:write(ip6t_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ip6t_bin .. '-restore -c' .. "\n") - f:write(ip6t_bin .. '-restore -n <<-EOT' .. "\n") - f:write(extract_rules("6", "filter") .. "\n") - f:write("EOT" .. "\n") - f:close() + if nft_flag == "0" then + f:write(ipt_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ipt_bin .. '-restore -c' .. "\n") + f:write(ipt_bin .. '-restore -n <<-EOT' .. "\n") + f:write(extract_rules("4", "filter") .. "\n") + f:write("EOT" .. "\n") + f:write(ip6t_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ip6t_bin .. '-restore -c' .. "\n") + f:write(ip6t_bin .. '-restore -n <<-EOT' .. "\n") + f:write(extract_rules("6", "filter") .. "\n") + f:write("EOT" .. "\n") + f:close() + else + f:write("nft -f " .. CONFIG_PATH .. "/" .. CONFIG .. ".nft\n") + f:write("nft insert rule inet fw4 input position 0 counter jump PSW-SERVER") + f:close() + end end end @@ -78,10 +91,15 @@ local function start() end cmd(string.format("mkdir -p %s %s", CONFIG_PATH, TMP_BIN_PATH)) cmd(string.format("touch %s", LOG_APP_FILE)) - ipt("-N PSW-SERVER") - ipt("-I INPUT -j PSW-SERVER") - ip6t("-N PSW-SERVER") - ip6t("-I INPUT -j PSW-SERVER") + if nft_flag == "0" then + ipt("-N PSW-SERVER") + ipt("-I INPUT -j PSW-SERVER") + ip6t("-N PSW-SERVER") + ip6t("-I INPUT -j PSW-SERVER") + else + cmd("nft add chain inet fw4 PSW-SERVER\n") + cmd("nft insert rule inet fw4 input position 0 counter jump PSW-SERVER") + end uci:foreach(CONFIG, "user", function(user) local id = user[".name"] local enable = user.enable @@ -168,12 +186,19 @@ local function start() local bind_local = user.bind_local or 0 if bind_local and tonumber(bind_local) ~= 1 then - ipt(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) - ip6t(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) - if udp_forward == 1 then - ipt(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) - ip6t(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) - end + if nft_flag == "0" then + ipt(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) + ip6t(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) + if udp_forward == 1 then + ipt(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) + ip6t(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) + end + else + cmd(string.format('nft add rule inet fw4 PSW-SERVER meta l4proto tcp tcp dport {%s} accept', port)) + if udp_forward == 1 then + cmd(string.format('nft add rule inet fw4 PSW-SERVER meta l4proto udp udp dport {%s} accept', port)) + end + end end end end) @@ -182,12 +207,19 @@ end local function stop() cmd(string.format("/bin/busybox top -bn1 | grep -v 'grep' | grep '%s/' | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1", CONFIG_PATH)) - ipt("-D INPUT -j PSW-SERVER 2>/dev/null") - ipt("-F PSW-SERVER 2>/dev/null") - ipt("-X PSW-SERVER 2>/dev/null") - ip6t("-D INPUT -j PSW-SERVER 2>/dev/null") - ip6t("-F PSW-SERVER 2>/dev/null") - ip6t("-X PSW-SERVER 2>/dev/null") + if nft_flag == "0" then + ipt("-D INPUT -j PSW-SERVER 2>/dev/null") + ipt("-F PSW-SERVER 2>/dev/null") + ipt("-X PSW-SERVER 2>/dev/null") + ip6t("-D INPUT -j PSW-SERVER 2>/dev/null") + ip6t("-F PSW-SERVER 2>/dev/null") + ip6t("-X PSW-SERVER 2>/dev/null") + else + nft_cmd="handles=$(nft -a list chain inet fw4 input | grep -E \"PSW-SERVER\" | awk -F '# handle ' '{print$2}')\n for handle in $handles; do\n nft delete rule inet fw4 input handle ${handle} 2>/dev/null\n done" + cmd(nft_cmd) + cmd("nft flush chain inet fw4 PSW-SERVER 2>/dev/null") + cmd("nft delete chain inet fw4 PSW-SERVER 2>/dev/null") + end cmd(string.format("rm -rf %s %s /tmp/etc/%s.include", CONFIG_PATH, LOG_APP_FILE, CONFIG)) end @@ -197,4 +229,4 @@ if action then elseif action == "stop" then stop() end -end \ No newline at end of file +end