Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
.gitattributes text eol=lf
*.sh text eol=lf
*.md text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
34 changes: 34 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: CI

on:
push:
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 10

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Install networking test dependencies
run: |
sudo apt-get update
sudo apt-get install -y iproute2 iptables nftables

- name: Check Bash syntax
run: |
bash -n nftpf.sh
bash -n tests/namespace-integration.sh

- name: Run renderer self-test
run: bash nftpf.sh --self-test

- name: Run isolated nftables integration test
run: sudo bash tests/namespace-integration.sh ./nftpf.sh
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Changelog

All notable changes to this project are documented in this file.

## [0.2.0] - 2026-07-10

### Added

- Added `nftpf --apply` for non-interactive validation, atomic loading, and boot persistence.
- Added `nftpf --self-test`, an isolated namespace integration test, and GitHub Actions CI.
- Added separate live-rule and boot-persistence status indicators.
- Added a `SHA256SUMS` release asset and a security-reporting policy.

### Changed

- Moved managed NAT rules from shared `ip nat` / `ip6 nat` tables into `nftpf_nat` tables.
- Replaced global service restarts with a validated atomic nftables transaction.
- Successful applies now enable `nftables.service` for reboot persistence.
- v0.1.x upgrades remove only nftpf's legacy lowercase NAT chains.

### Fixed

- Preserved unrelated nftables and iptables-nft rules used by Phantun, Docker, fail2ban, and other tools.
- Made stop and uninstall remove only nftpf-managed tables instead of flushing the global ruleset.
- Added rollback for failed rule, line, access-control, backup-import, and service-enable operations.
- Normalized duplicate forwarding keys in `/etc/sysctl.conf` without loose regular-expression matching.
8 changes: 6 additions & 2 deletions NFT_Port_Forwarding_Tool_PRD.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# NFT Port Forwarding Tool PRD

> Status: historical design document. It records the original implementation plan and v0.1.x baseline. See `README.md` and `CHANGELOG.md` for current v0.2.x behavior.

## 1. Document Info

Product name: NFT Port Forwarding Tool
Expand All @@ -8,7 +10,7 @@ Document type: Product Requirements Document

Target platform: Linux servers using nftables

Primary script: `nft_helper.sh`
Primary script: `nftpf.sh`

Baseline version: Initial IPv4-only script from `C:/Users/endin/Downloads/nft_helper.sh`

Expand Down Expand Up @@ -101,7 +103,9 @@ Secondary users:

9. As a user, I can enter a DDNS domain as the target address in a future version and have the tool keep it updated.

## 8. Current Baseline Behavior
## 8. Historical v0.1.x Baseline Behavior

The global `flush ruleset` structure below is retained only as historical context. v0.2.0 and later use namespaced `nftpf_*` tables and atomically replace only those managed tables.

The initial script uses this default nftables structure:

Expand Down
49 changes: 38 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
- Add single-port forwarding rules for TCP and UDP.
- Add port-range forwarding rules with 1:1 or offset mapping.
- Support IPv4, IPv6, and domain/DDNS targets.
- Automatically validate nftables configuration before applying changes.
- Automatically apply changes by starting or restarting the nftables service.
- Validate the complete nftables transaction before changing live rules.
- Atomically replace only `nftpf_*` tables without restarting the global nftables service.
- Enable nftables at boot whenever rules are applied, while reporting live-rule and boot-persistence status separately.
- Coexist with rules managed by iptables-nft, Phantun, Docker, fail2ban, and other tools.
- Detect and repair managed nftables configuration drift on startup.
- Support DDNS refresh with optional systemd timer automation.
- Support mutually exclusive whitelist/blacklist access control for managed forwarding ports.
Expand All @@ -24,7 +26,10 @@
## Quick Start

```bash
curl -L -o nftpf.sh https://github.com/endview/nftpf/releases/latest/download/nftpf.sh
curl -fL --proto '=https' --tlsv1.2 -o nftpf.sh https://github.com/endview/nftpf/releases/latest/download/nftpf.sh
curl -fL --proto '=https' --tlsv1.2 -o SHA256SUMS https://github.com/endview/nftpf/releases/latest/download/SHA256SUMS
sha256sum -c SHA256SUMS
bash -n nftpf.sh
chmod +x nftpf.sh
sudo bash nftpf.sh
```
Expand All @@ -35,15 +40,13 @@ After the first run, the tool installs a shortcut:
nftpf
```

## Important Notice
## Safe Rule Ownership And Persistence

The generated nftables configuration contains:
Starting with v0.2.0, generated configuration does not contain `flush ruleset`. `nftpf` owns only tables whose names begin with `nftpf_`, validates a delete-and-recreate transaction first, and then commits that transaction atomically. Unrelated nftables and iptables-nft tables remain loaded.

```nft
flush ruleset
```
When upgrading a v0.1.x configuration, the one-time migration removes only the legacy lowercase `prerouting` and `postrouting` chains created by `nftpf` inside `table ip nat` / `table ip6 nat`. Uppercase iptables-nft chains such as `PREROUTING` and `POSTROUTING` are preserved.

That means this tool rewrites the current nftables ruleset when applying managed configuration. Do not use it on hosts where other firewall tools or applications also manage nftables rules unless you understand and accept that behavior.
Every successful apply also enables `nftables.service` for boot persistence. Use `nftpf --apply` to validate, atomically load, and persist the managed rules. Avoid manually restarting the global nftables service on a host shared with other firewall managers, because some distribution service units flush the complete live ruleset during restart.

## DDNS Refresh

Expand Down Expand Up @@ -77,21 +80,44 @@ The default line mode only binds the entry interface and does not change system

## Backup And Rollback

Before changing forwarding rules or access-control settings, `nftpf` automatically creates a backup under `/etc/nft-port-forward/backups`. The menu also provides manual backup, import, and rollback to the latest automatic backup.
Before changing forwarding rules or access-control settings, `nftpf` automatically creates a backup under `/etc/nft-port-forward/backups`. The menu also provides manual backup, import, and rollback to the latest automatic backup. Failed applies restore the previous state files, generated configuration, and service-enable state.

For non-destructive checks, run `nftpf --self-test`. This verifies Bash syntax and renderer invariants without changing system rules.

## Tests

Run the fast checks on any Linux host:

```bash
bash -n nftpf.sh
bash nftpf.sh --self-test
```

The integration test requires root plus `iproute2`, `iptables`, and `nftables`. It creates an isolated network namespace, migrates a simulated v0.1.x ruleset, and verifies that foreign iptables-nft rules survive migration, reapply, failed transactions, and cleanup. It does not modify the host network namespace.

```bash
sudo bash tests/namespace-integration.sh ./nftpf.sh
```

The same checks run automatically through GitHub Actions.

## Script Update

Use menu item `17. 更新脚本` or run `nftpf --update` to download the latest `nftpf.sh` from GitHub Releases. The updater validates the downloaded script and creates a `.bak.<timestamp>` backup before replacing the local script. Updating the script does not change forwarding rules and does not restart nftables.

## Uninstall

Use menu item `18. 卸载脚本` or run `nftpf --uninstall` to remove nftpf. The uninstall flow clears the current nftables ruleset, resets nftpf-managed configuration to an empty ruleset, removes DDNS timers/services, removes managed policy-route services and rules, removes state files, and deletes the installed script/shortcut. Backup deletion is optional and defaults to `N`.
Use menu item `18. 卸载脚本` or run `nftpf --uninstall` to remove nftpf. The uninstall flow removes only nftpf-managed tables, resets nftpf-managed configuration to an empty file, removes DDNS timers/services, removes managed policy-route services and rules, removes state files, and deletes the installed script/shortcut. Backup deletion is optional and defaults to `N`.

The uninstall flow does not remove the `nftables` package and does not disable system IP forwarding sysctl settings, because those may be used by other services.

## Files

- `nftpf.sh`: Main script.
- `tests/namespace-integration.sh`: Isolated migration and coexistence regression test.
- `.github/workflows/ci.yml`: GitHub Actions validation workflow.
- `CHANGELOG.md`: Versioned change history.
- `SECURITY.md`: Supported versions and private vulnerability-reporting guidance.
- `NFT_Port_Forwarding_Tool_PRD.md`: Product requirements and design notes.

## Requirements
Expand All @@ -101,6 +127,7 @@ The uninstall flow does not remove the `nftables` package and does not disable s
- `bash`.
- `nftables`.
- `iproute2`.
- Debian/Ubuntu for automatic nftables installation. On other systemd distributions, install nftables manually first.
- Optional: `flock` from `util-linux` for DDNS refresh locking.

## License
Expand Down
49 changes: 38 additions & 11 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
- 添加单端口 TCP+UDP 转发规则。
- 添加端口段转发规则,支持 1:1 映射和偏移映射。
- 支持 IPv4、IPv6、域名/DDNS 目标。
- 写入配置前自动校验 nftables 语法。
- 规则变更后自动启动或重启 nftables 服务,使配置立即生效。
- 修改实时规则前校验完整 nftables 事务。
- 原子替换 `nftpf_*` 托管表,不重启全局 nftables 服务。
- 每次成功应用规则时启用 nftables 开机自启,并分别显示实时规则与开机持久化状态。
- 可与 iptables-nft、Phantun、Docker、fail2ban 等工具管理的规则共存。
- 启动时自动检测并修复本工具托管的 nftables 配置漂移。
- 支持 DDNS 手动刷新和 systemd timer 自动刷新。
- 支持白名单/黑名单二选一的访问控制,只限制本工具托管的转发端口。
Expand All @@ -24,7 +26,10 @@
## 快速开始

```bash
curl -L -o nftpf.sh https://github.com/endview/nftpf/releases/latest/download/nftpf.sh
curl -fL --proto '=https' --tlsv1.2 -o nftpf.sh https://github.com/endview/nftpf/releases/latest/download/nftpf.sh
curl -fL --proto '=https' --tlsv1.2 -o SHA256SUMS https://github.com/endview/nftpf/releases/latest/download/SHA256SUMS
sha256sum -c SHA256SUMS
bash -n nftpf.sh
chmod +x nftpf.sh
sudo bash nftpf.sh
```
Expand All @@ -35,15 +40,13 @@ sudo bash nftpf.sh
nftpf
```

## 重要提示
## 规则隔离与持久化

本工具生成的 nftables 配置包含:
从 v0.2.0 开始,生成的配置不再包含 `flush ruleset`。`nftpf` 只管理名称以 `nftpf_` 开头的表;应用前会校验“删除旧托管表并创建新托管表”的完整事务,校验通过后一次性原子提交,不会清除其它 nftables 或 iptables-nft 表。

```nft
flush ruleset
```
从 v0.1.x 升级时,一次性迁移只删除 `nftpf` 旧版在 `table ip nat` / `table ip6 nat` 中创建的小写 `prerouting`、`postrouting` 链;iptables-nft 使用的大写 `PREROUTING`、`POSTROUTING` 等链会保留。

这意味着应用本工具托管配置时,会重写当前 nftables 规则集。如果你的服务器上还有 Docker、fail2ban、防火墙面板或其他程序也在管理 nftables,请先确认你能接受这个行为后再使用
每次成功应用都会启用 `nftables.service` 开机自启。可以运行 `nftpf --apply` 校验、原子加载并持久化托管规则。如果主机同时运行其它防火墙管理程序,请避免手动重启全局 nftables 服务,因为部分发行版的 service 在重启时会清空整个实时 ruleset

## DDNS 刷新

Expand Down Expand Up @@ -81,21 +84,44 @@ Unit=nftpf-ddns.service

## 备份和回滚

每次修改转发规则或访问控制设置前,`nftpf` 会自动在 `/etc/nft-port-forward/backups` 下创建备份。菜单也提供手动备份、导入备份,以及回滚到上一次自动备份。
每次修改转发规则或访问控制设置前,`nftpf` 会自动在 `/etc/nft-port-forward/backups` 下创建备份。菜单也提供手动备份、导入备份,以及回滚到上一次自动备份。应用失败时会恢复之前的状态文件、生成配置和服务启用状态。

可以运行 `nftpf --self-test` 做无侵入检查;该命令验证 Bash 语法和配置渲染约束,不修改系统规则。

## 测试

普通 Linux 主机可以运行快速检查:

```bash
bash -n nftpf.sh
bash nftpf.sh --self-test
```

集成测试需要 root,以及 `iproute2`、`iptables`、`nftables`。测试会创建隔离网络命名空间,模拟 v0.1.x 规则迁移,并验证外部 iptables-nft 规则在迁移、重复应用、错误事务和清理后仍保持不变;不会修改宿主网络命名空间。

```bash
sudo bash tests/namespace-integration.sh ./nftpf.sh
```

GitHub Actions 会自动运行同一组检查。

## 脚本更新

可以使用菜单 `17. 更新脚本`,也可以运行 `nftpf --update`。更新会从 GitHub Releases 下载最新版 `nftpf.sh`,先校验脚本标识和 bash 语法,再备份当前脚本为 `.bak.<时间戳>` 后替换。更新脚本不会修改现有转发规则,也不会重启 nftables。

## 卸载

可以使用菜单 `18. 卸载脚本`,也可以运行 `nftpf --uninstall`。卸载流程会清空当前 nftables ruleset,将 nftpf 托管配置重置为空规则,删除 DDNS timer/service、旧 cron 任务、多网卡托管回程 service 和 nftpf 创建的 fwmark/ip rule/路由表,删除状态文件,并删除已安装脚本和快捷命令。是否删除备份文件会单独询问,默认 `N` 保留。
可以使用菜单 `18. 卸载脚本`,也可以运行 `nftpf --uninstall`。卸载流程只删除 nftpf 托管表,将 nftpf 托管配置重置为空文件,删除 DDNS timer/service、旧 cron 任务、多网卡托管回程 service 和 nftpf 创建的 fwmark/ip rule/路由表,删除状态文件,并删除已安装脚本和快捷命令。是否删除备份文件会单独询问,默认 `N` 保留。

卸载不会删除 `nftables` 软件包,也不会关闭系统 IP 转发 sysctl,因为这些可能被其它服务使用。

## 文件说明

- `nftpf.sh`:主脚本。
- `tests/namespace-integration.sh`:隔离的迁移与共存回归测试。
- `.github/workflows/ci.yml`:GitHub Actions 自动校验流程。
- `CHANGELOG.md`:按版本维护的变更记录。
- `SECURITY.md`:支持版本和私密漏洞报告说明。
- `NFT_Port_Forwarding_Tool_PRD.md`:产品需求和设计说明。

## 环境要求
Expand All @@ -105,6 +131,7 @@ Unit=nftpf-ddns.service
- `bash`。
- `nftables`。
- `iproute2`。
- Debian/Ubuntu 可自动安装 nftables;其它 systemd 发行版请先手动安装。
- 可选:`util-linux` 中的 `flock`,用于 DDNS 刷新防重叠执行。

## 许可证
Expand Down
Loading
Loading