Document installation and validate shell scripts
This commit is contained in:
221
README.md
221
README.md
@@ -1,3 +1,222 @@
|
|||||||
# IPTables-Management
|
# IPTables-Management
|
||||||
|
|
||||||
IPTables转发管理脚本
|
一个基于 Bash 的中文交互式 IPTables 端口转发管理工具,面向 Debian 12/13。
|
||||||
|
|
||||||
|
- 启动时自动做环境自检。
|
||||||
|
- 仅管理本工具创建的 `MGMT:<UUID>` 规则。
|
||||||
|
- 支持 TCP / UDP / both,支持 IPv4 / IPv6 / both。
|
||||||
|
- 支持 `iptables-persistent` / `netfilter-persistent save` 持久化。
|
||||||
|
- 附带单元测试与真实 iptables 集成测试。
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
.
|
||||||
|
├── iptables-forward.sh # 主入口
|
||||||
|
├── install.sh # 创建 /usr/local/bin/iptables-forward 符号链接
|
||||||
|
├── lib/ # 业务模块
|
||||||
|
├── tests/ # 测试与 mock
|
||||||
|
└── plan_iptables_forward.md # 实施方案
|
||||||
|
```
|
||||||
|
|
||||||
|
## 运行要求
|
||||||
|
|
||||||
|
- Debian 12/13
|
||||||
|
- Bash 4+
|
||||||
|
- root 或 sudo
|
||||||
|
- `iptables`
|
||||||
|
- `ip6tables`
|
||||||
|
- `iptables-persistent`(提供 `netfilter-persistent`)
|
||||||
|
|
||||||
|
> 首次运行若缺依赖,脚本会列出缺失项并询问是否自动安装。
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
### 直接运行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./iptables-forward.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 安装到 PATH
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./install.sh
|
||||||
|
sudo iptables-forward
|
||||||
|
```
|
||||||
|
|
||||||
|
默认会创建:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/usr/local/bin/iptables-forward -> /path/to/IPTables-Management/iptables-forward.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
### 交互模式
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./iptables-forward.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
主菜单提供:
|
||||||
|
|
||||||
|
- 查看所有转发规则
|
||||||
|
- 添加新的转发规则
|
||||||
|
- 删除现有转发规则
|
||||||
|
- 查看系统环境状态
|
||||||
|
- 立即保存到磁盘
|
||||||
|
- 退出
|
||||||
|
|
||||||
|
### 批处理模式
|
||||||
|
|
||||||
|
用于自动化测试或脚本调用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./iptables-forward.sh --batch add <proto> <listen_port> <target_ip> <target_port> <ipver> [desc]
|
||||||
|
sudo ./iptables-forward.sh --batch delete <uuid>
|
||||||
|
sudo ./iptables-forward.sh --batch list
|
||||||
|
sudo ./iptables-forward.sh --batch save
|
||||||
|
```
|
||||||
|
|
||||||
|
参数说明:
|
||||||
|
|
||||||
|
- `proto`: `tcp` / `udp` / `both`
|
||||||
|
- `ipver`: `4` / `6` / `both`
|
||||||
|
- `target_ip`:
|
||||||
|
- `ipver=4` 时传单个 IPv4
|
||||||
|
- `ipver=6` 时传单个 IPv6
|
||||||
|
- `ipver=both` 时传 `IPv4,IPv6`,例如 `127.0.0.1,::1`
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./iptables-forward.sh --batch add tcp 8080 192.168.1.100 80 4 "web"
|
||||||
|
sudo ./iptables-forward.sh --batch add both 5353 127.0.0.1,::1 53 both "dns"
|
||||||
|
```
|
||||||
|
|
||||||
|
成功时标准输出会返回新规则 UUID。
|
||||||
|
|
||||||
|
## 存储与持久化
|
||||||
|
|
||||||
|
规则元数据默认保存在:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/var/lib/iptables-forward/rules.db
|
||||||
|
```
|
||||||
|
|
||||||
|
格式为一行一条:
|
||||||
|
|
||||||
|
```text
|
||||||
|
uuid=a1b2c3d4|proto=tcp|lport=8080|tip=192.168.1.100|tport=80|ipver=4|desc=web|created=2026-04-17T10:00:00+0800
|
||||||
|
```
|
||||||
|
|
||||||
|
添加/删除规则时会自动调用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
netfilter-persistent save
|
||||||
|
```
|
||||||
|
|
||||||
|
以便把规则保存到:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/iptables/rules.v4
|
||||||
|
/etc/iptables/rules.v6
|
||||||
|
```
|
||||||
|
|
||||||
|
## 测试
|
||||||
|
|
||||||
|
### 运行全部测试
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tests/run_all.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 跳过集成测试
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tests/run_all.sh --skip-integration
|
||||||
|
```
|
||||||
|
|
||||||
|
测试覆盖:
|
||||||
|
|
||||||
|
- `tests/test_common.sh`:输入校验
|
||||||
|
- `tests/test_storage.sh`:规则存储
|
||||||
|
- `tests/test_env_check.sh`:环境检查与修复
|
||||||
|
- `tests/test_rules_unit.sh`:mock iptables 下的增删回滚
|
||||||
|
- `tests/test_integration.sh`:真实 iptables 生命周期测试
|
||||||
|
|
||||||
|
`tests/test_integration.sh` 的执行策略:
|
||||||
|
|
||||||
|
- root 环境下直接执行
|
||||||
|
- 非 root 但支持 `unshare -Urn` 时,会进入隔离网络命名空间执行
|
||||||
|
- 两者都不满足时会输出 `SKIP`
|
||||||
|
|
||||||
|
## 手工验收建议
|
||||||
|
|
||||||
|
建议按 `plan_iptables_forward.md` 再做以下实机验证:
|
||||||
|
|
||||||
|
1. 在干净 Debian 12/13 上首次启动,确认自动安装流程可用。
|
||||||
|
2. 准备一台实际后端服务主机,验证从第三方主机访问转发端口时流量确实命中目标服务。
|
||||||
|
3. 重启系统后确认规则仍存在,且菜单中状态仍为健康。
|
||||||
|
4. 删除规则后再次验证外部访问失败。
|
||||||
|
|
||||||
|
## 故障排查
|
||||||
|
|
||||||
|
### 1. 提示必须使用 root
|
||||||
|
|
||||||
|
脚本必须以 root 执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./iptables-forward.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 自动安装失败
|
||||||
|
|
||||||
|
可手动安装依赖后重试:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y iptables iptables-persistent
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 持久化保存失败
|
||||||
|
|
||||||
|
确认以下命令可执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
command -v netfilter-persistent
|
||||||
|
sudo netfilter-persistent save
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 系统使用 nft 后端
|
||||||
|
|
||||||
|
Debian 12/13 默认常见为 `iptables-nft`。本项目不自动切换到 legacy 后端,而是依赖发行版默认配置。
|
||||||
|
|
||||||
|
### 5. 其它防火墙工具干扰
|
||||||
|
|
||||||
|
若系统启用了 `ufw` 或 `firewalld`,可能覆盖或影响转发规则。脚本会给出黄色警告,但不会自动关闭这些服务。
|
||||||
|
|
||||||
|
## 卸载
|
||||||
|
|
||||||
|
### 删除 PATH 链接
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./install.sh --uninstall
|
||||||
|
```
|
||||||
|
|
||||||
|
### 删除脚本管理的规则与状态
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo iptables-save | grep -v 'MGMT:' | sudo iptables-restore
|
||||||
|
sudo ip6tables-save | grep -v 'MGMT:' | sudo ip6tables-restore
|
||||||
|
sudo netfilter-persistent save
|
||||||
|
sudo rm -rf /var/lib/iptables-forward
|
||||||
|
sudo rm -f /etc/sysctl.d/99-iptables-forward.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### 可选:卸载持久化包
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt-get remove --purge iptables-persistent
|
||||||
|
```
|
||||||
|
|||||||
68
install.sh
Normal file
68
install.sh
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||||
|
SOURCE_SCRIPT="${SCRIPT_DIR}/iptables-forward.sh"
|
||||||
|
TARGET_BIN=${INSTALL_TARGET:-/usr/local/bin/iptables-forward}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<USAGE
|
||||||
|
用法:
|
||||||
|
sudo ./install.sh
|
||||||
|
sudo ./install.sh --uninstall
|
||||||
|
|
||||||
|
说明:
|
||||||
|
- 仅创建符号链接,不复制源码。
|
||||||
|
- 默认链接到 /usr/local/bin/iptables-forward。
|
||||||
|
- 可通过 INSTALL_TARGET 自定义目标路径。
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
require_root() {
|
||||||
|
if (( EUID != 0 )); then
|
||||||
|
printf '请使用 root 或 sudo 执行安装脚本。\n' >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_link() {
|
||||||
|
[[ -f ${SOURCE_SCRIPT} ]] || {
|
||||||
|
printf '未找到入口脚本: %s\n' "${SOURCE_SCRIPT}" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
mkdir -p "$(dirname -- "${TARGET_BIN}")"
|
||||||
|
ln -sfn "${SOURCE_SCRIPT}" "${TARGET_BIN}"
|
||||||
|
chmod 755 "${SOURCE_SCRIPT}"
|
||||||
|
printf '已创建链接: %s -> %s\n' "${TARGET_BIN}" "${SOURCE_SCRIPT}"
|
||||||
|
}
|
||||||
|
|
||||||
|
uninstall_link() {
|
||||||
|
if [[ -L ${TARGET_BIN} || -e ${TARGET_BIN} ]]; then
|
||||||
|
rm -f "${TARGET_BIN}"
|
||||||
|
printf '已删除链接: %s\n' "${TARGET_BIN}"
|
||||||
|
else
|
||||||
|
printf '未发现已安装链接: %s\n' "${TARGET_BIN}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
case ${1:-install} in
|
||||||
|
--help|-h)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
install)
|
||||||
|
require_root
|
||||||
|
install_link
|
||||||
|
;;
|
||||||
|
--uninstall|uninstall)
|
||||||
|
require_root
|
||||||
|
uninstall_link
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
@@ -18,18 +18,12 @@ if [[ ${IPF_COLOR_ENABLED} == 1 ]]; then
|
|||||||
CLR_GREEN=$'\033[32m'
|
CLR_GREEN=$'\033[32m'
|
||||||
CLR_YELLOW=$'\033[33m'
|
CLR_YELLOW=$'\033[33m'
|
||||||
CLR_BLUE=$'\033[34m'
|
CLR_BLUE=$'\033[34m'
|
||||||
CLR_CYAN=$'\033[36m'
|
|
||||||
CLR_BOLD=$'\033[1m'
|
|
||||||
CLR_DIM=$'\033[2m'
|
|
||||||
CLR_RESET=$'\033[0m'
|
CLR_RESET=$'\033[0m'
|
||||||
else
|
else
|
||||||
CLR_RED=''
|
CLR_RED=''
|
||||||
CLR_GREEN=''
|
CLR_GREEN=''
|
||||||
CLR_YELLOW=''
|
CLR_YELLOW=''
|
||||||
CLR_BLUE=''
|
CLR_BLUE=''
|
||||||
CLR_CYAN=''
|
|
||||||
CLR_BOLD=''
|
|
||||||
CLR_DIM=''
|
|
||||||
CLR_RESET=''
|
CLR_RESET=''
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user