mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-01 16:44:23 +08:00
111 lines
4.3 KiB
Bash
111 lines
4.3 KiB
Bash
# SPDX-License-Identifier: GPL-2.0-only
|
|
#
|
|
# Copyright (C) 2025 ImmortalWrt.org
|
|
#
|
|
# fw4 integration for homeproxy-pro.
|
|
#
|
|
# homeproxy-pro owns a fixed set of nft chains and sets inside the `fw4` table.
|
|
# They are created by the rendered template (firewall_post.ut, applied by
|
|
# `fw4 reload`) and torn down one object at a time on stop. All of that used
|
|
# to live inline in /etc/init.d/homeproxy-pro.
|
|
#
|
|
# Layering note: this is a device-side module. It calls `log` and, for the
|
|
# teardown, requires the HP_FW4_CHAINS / HP_FW4_SETS inventory to be in scope
|
|
# (root/etc/homeproxy-pro/scripts/fw4_names.sh, sourced by init.d).
|
|
#
|
|
# Sourced by /etc/init.d/homeproxy-pro.
|
|
|
|
# hp_restore_upnp_mappings
|
|
# fw4 reload rewrites the whole ruleset, which drops the miniupnpd mappings,
|
|
# so ask miniupnpd to reinstall them - but only when it is actually enabled
|
|
# and running.
|
|
hp_restore_upnp_mappings() {
|
|
[ -x /etc/init.d/miniupnpd ] && /etc/init.d/miniupnpd enabled && /etc/init.d/miniupnpd running \
|
|
&& /etc/init.d/miniupnpd restart >"/dev/null" 2>&1
|
|
}
|
|
|
|
# hp_firewall_apply <hp-dir> <run-dir> <client-enabled>
|
|
# Run the pre-script, render the post-template for the client side, reload
|
|
# fw4 and restore the upnp mappings. <client-enabled> is "1" when a client
|
|
# outbound exists; the post-template is client-only.
|
|
hp_firewall_apply() {
|
|
local hp_dir="$1"
|
|
local run_dir="$2"
|
|
local client_enabled="$3"
|
|
|
|
local failed=0
|
|
|
|
# Truncate the include fragments first. firewall_pre.uc only writes them
|
|
# when it has something to put in them, so a start that produces no
|
|
# forward/input rules would leave the previous run's files in place and fw4
|
|
# would keep loading them. teardown already truncates for the same reason.
|
|
: > "$run_dir/fw4_forward.nft"
|
|
: > "$run_dir/fw4_input.nft"
|
|
|
|
ucode "$hp_dir/scripts/firewall_pre.uc" 2>"/dev/null" \
|
|
|| { log "Error: firewall pre-script failed."; failed=1; }
|
|
|
|
if [ "$client_enabled" = "1" ]; then
|
|
# Render to a temp file and install it only on success. The old
|
|
# `> "$run_dir/fw4_post.nft"` truncated the very file fw4 is about to
|
|
# include, so a failed render left fw4 loading an empty ruleset.
|
|
if utpl -S "$hp_dir/scripts/firewall_post.ut" > "$run_dir/fw4_post.nft.new" 2>"/dev/null"; then
|
|
mv -f "$run_dir/fw4_post.nft.new" "$run_dir/fw4_post.nft"
|
|
else
|
|
rm -f "$run_dir/fw4_post.nft.new"
|
|
log "Error: firewall post-script failed."
|
|
failed=1
|
|
fi
|
|
fi
|
|
|
|
fw4 reload >"/dev/null" 2>&1 \
|
|
|| { log "Error: fw4 reload failed."; failed=1; }
|
|
|
|
# The return value has to describe this function, not whatever
|
|
# hp_restore_upnp_mappings happened to return last.
|
|
hp_restore_upnp_mappings
|
|
|
|
return "$failed"
|
|
}
|
|
|
|
# hp_firewall_teardown <run-dir> [keep-pre]
|
|
# Flush and delete every fw4 object homeproxy-pro owns. Deleting one at a time
|
|
# matters: `nft -f` batches are atomic, so a single object that does not
|
|
# exist in the current proxy mode would roll back the rest.
|
|
#
|
|
# "keep-pre" leaves fw4_forward.nft / fw4_input.nft alone. Those two are the
|
|
# firewall_pre.uc fragments - the server's inbound accepts and the TUN
|
|
# forwards - and they are not what black-holes the LAN when the client fails.
|
|
# A failed client has to release the redirect/tproxy layer without closing
|
|
# the server's ports, so that path passes keep-pre; stop_service does not.
|
|
hp_firewall_teardown() {
|
|
local run_dir="$1"
|
|
local keep_pre="${2:-}"
|
|
local fw4_name
|
|
|
|
for fw4_name in $HP_FW4_CHAINS; do
|
|
nft flush chain inet fw4 "$fw4_name" 2>"/dev/null"
|
|
nft delete chain inet fw4 "$fw4_name" 2>"/dev/null"
|
|
done
|
|
for fw4_name in $HP_FW4_SETS; do
|
|
nft flush set inet fw4 "$fw4_name" 2>"/dev/null"
|
|
nft delete set inet fw4 "$fw4_name" 2>"/dev/null"
|
|
done
|
|
|
|
if [ "$keep_pre" != "keep-pre" ]; then
|
|
: > "$run_dir/fw4_forward.nft"
|
|
: > "$run_dir/fw4_input.nft"
|
|
fi
|
|
: > "$run_dir/fw4_post.nft"
|
|
|
|
# Stop-time fw4 reload is best-effort on purpose: every homeproxy-pro-owned
|
|
# chain and set has already been flushed and deleted above, so the
|
|
# live ruleset no longer references them. A reload that succeeds here
|
|
# also re-loads /etc/config/firewall; a reload that fails leaves the
|
|
# rest of the user's ruleset untouched, which is the safer outcome -
|
|
# logging a Warning used to suggest the stop had lost something when
|
|
# in fact nothing homeproxy-pro-owned was left to lose.
|
|
fw4 reload >"/dev/null" 2>&1 || true
|
|
hp_restore_upnp_mappings
|
|
}
|