Files
IPTables-Management/iptables-forward.sh
ahdoawhfo 26fbcf3584 Mark runnable scripts executable in git
The repo was committed from WSL with core.filemode=false, so the exec
bit was never recorded. After actions/checkout the entry script comes
down as 100644 and tests/test_cli.sh fails with Permission denied.

Set mode 100755 on every script that is invoked directly (entry,
installer, test suite, mock binaries). Sourced helpers under lib/
keep 100644 per convention.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 13:58:42 +08:00

183 lines
3.6 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -Eeuo pipefail
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
LIB_DIR=${SCRIPT_DIR}/lib
# shellcheck source=lib/common.sh
source "${LIB_DIR}/common.sh"
on_error() {
local exit_code=$1
local line_no=$2
log_err "脚本在第 ${line_no} 行发生错误,退出码 ${exit_code}"
exit "${exit_code}"
}
trap 'on_error "$?" "$LINENO"' ERR
# shellcheck source=lib/storage.sh
source "${LIB_DIR}/storage.sh"
# shellcheck source=lib/persist.sh
source "${LIB_DIR}/persist.sh"
# shellcheck source=lib/iptables_ops.sh
source "${LIB_DIR}/iptables_ops.sh"
# shellcheck source=lib/env_check.sh
source "${LIB_DIR}/env_check.sh"
# shellcheck source=lib/rules_mgr.sh
source "${LIB_DIR}/rules_mgr.sh"
: "${IPF_SKIP_ENV_CHECK:=0}"
usage() {
cat <<USAGE
用法:
./iptables-forward.sh
./iptables-forward.sh --batch add <proto> <listen_port> <target_ip> <target_port> <ipver> [desc]
./iptables-forward.sh --batch delete <uuid>
./iptables-forward.sh --batch list
./iptables-forward.sh --batch save
./iptables-forward.sh --batch env
./iptables-forward.sh --help
说明:
- proto: tcp / udp / both
- ipver: 4 / 6 / both
- 当 ipver=both 时target_ip 需使用 IPv4,IPv6 形式,例如 127.0.0.1,::1
USAGE
}
MENU_LINES=(
'[1] 查看所有转发规则'
'[2] 添加新的转发规则'
'[3] 删除现有转发规则'
'[4] 查看系统环境状态'
'[5] 立即保存到磁盘'
'[0] 退出'
)
bootstrap() {
if [[ ${IPF_SKIP_ENV_CHECK} != 1 ]]; then
env_check_all
fi
storage_init
}
render_main_menu() {
local status persist runtime count width line
status=$(env_status_summary)
count=$(storage_count)
runtime=$(rules_runtime_mark)
if persist_available; then
persist='[✓]'
else
persist='[!]'
fi
if use_box_ui; then
width=$(box_width)
box_top "${width}"
box_line "${width}" "${IPF_APP_NAME}"
box_separator "${width}"
box_line "${width}" "状态: ${status} 规则数: ${count} 持久化: ${persist} 运行态: ${runtime}"
box_separator "${width}"
for line in "${MENU_LINES[@]}"; do
box_line "${width}" "${line}"
done
box_bottom "${width}"
else
printf '%s\n' "${IPF_APP_NAME}"
printf '状态: %s | 规则数: %s | 持久化: %s | 运行态: %s\n' "${status}" "${count}" "${persist}" "${runtime}"
printf '%s\n' "${MENU_LINES[@]}"
fi
}
main_menu_loop() {
local choice
while true; do
render_main_menu
prompt_input_capture '请选择 [0-5]' ''
choice=${PROMPT_INPUT_RESULT}
case ${choice} in
1) cmd_list ;;
2) cmd_add ;;
3) cmd_delete ;;
4) cmd_show_env_status ;;
5)
cmd_save_rules
pause_return
;;
0)
log_info '已退出。'
return 0
;;
*)
log_warn '无效选择,请输入 0-5。'
;;
esac
done
}
run_batch() {
local action=${1-}
shift || true
case ${action} in
add)
if (($# < 5)); then
usage
return 1
fi
cmd_add_batch "$@"
;;
delete)
if (($# != 1)); then
usage
return 1
fi
cmd_delete_uuid "$1"
;;
list)
storage_list
;;
save)
cmd_save_rules
;;
env)
env_check_all
;;
*)
usage
return 1
;;
esac
}
main() {
case ${1-} in
--help|-h)
usage
return 0
;;
esac
require_root || return $?
bootstrap
if (($# == 0)); then
main_menu_loop
return 0
fi
case ${1-} in
--batch)
shift
run_batch "$@"
;;
*)
usage
return 1
;;
esac
}
main "$@"