diff --git a/Forward-Tools/nftables_tools.sh b/Forward-Tools/nftables_tools.sh new file mode 100644 index 0000000..e54ac24 --- /dev/null +++ b/Forward-Tools/nftables_tools.sh @@ -0,0 +1,151 @@ +#!/bin/bash + +# 确保脚本以 root 权限运行 +if [[ $EUID -ne 0 ]]; then + echo "错误:本脚本必须以 root 权限运行" + exit 1 +fi + +# 检查是否安装了 nftables +if ! command -v nft &> /dev/null; then + echo "未检查到 nftables,正在尝试安装..." + if command -v apt-get &> /dev/null; then + apt-get update -y && apt-get install -y nftables + elif command -v yum &> /dev/null; then + yum install -y nftables + else + echo "错误:无法自动安装 nftables,请手动安装后重试。" + exit 1 + fi + systemctl enable nftables --now +fi + +# 初始化 nftables 的 nat 表和链 +function init_nftables() { + nft list table ip nat &>/dev/null + if [ $? -ne 0 ]; then + echo "" + read -p "首次初始化,请输入外部网络接口名称 (oifname, 例如 eth0): " eth_name + if [[ -z "$eth_name" ]]; then + eth_name="eth0" + echo "未输入,默认使用 eth0" + fi + + nft add table ip nat + # prerouting 链用于 DNAT (修改目标地址) + nft add chain ip nat prerouting { type nat hook prerouting priority 0 \; policy accept \; } + # postrouting 链用于 SNAT/masquerade (修改源地址) + nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; policy accept \; } + + # 添加通用 masquerade 规则 + nft add rule ip nat postrouting oifname "$eth_name" masquerade + fi +} + +function save_rules() { + echo "正在保存 nftables 规则..." + if [ -f /etc/redhat-release ]; then + nft list ruleset > /etc/sysconfig/nftables.conf || echo "保存失败" + else + nft list ruleset > /etc/nftables.conf || echo "保存失败" + fi + echo "规则保存完毕。" +} + +function add_rule() { + init_nftables + + echo "" + read -p "请输入本地监听端口 (例如 8080): " local_port + read -p "请输入目标 IP 地址 (例如 10.0.0.2): " dest_ip + read -p "请输入目标端口 (不输入则默认和本地监听端口一致): " dest_port + read -p "请输入转发协议 (tcp/udp/both) [默认: both]: " protocol + protocol=${protocol:-both} + + if [[ -z "$dest_port" ]]; then + dest_port=$local_port + fi + + if [[ -z "$local_port" || -z "$dest_ip" ]]; then + echo "本地端口和目标IP不能为空,操作取消。" + return + fi + + echo "正在添加规则..." + + if [[ "$protocol" == "tcp" || "$protocol" == "both" ]]; then + if [[ "$local_port" == "$dest_port" ]]; then + nft add rule ip nat prerouting tcp dport $local_port dnat to $dest_ip + else + nft add rule ip nat prerouting tcp dport $local_port dnat to $dest_ip:$dest_port + fi + fi + + if [[ "$protocol" == "udp" || "$protocol" == "both" ]]; then + if [[ "$local_port" == "$dest_port" ]]; then + nft add rule ip nat prerouting udp dport $local_port dnat to $dest_ip + else + nft add rule ip nat prerouting udp dport $local_port dnat to $dest_ip:$dest_port + fi + fi + + echo -e "\n成功添加端口转发规则: 本机:$local_port -> $dest_ip:$dest_port (协议: $protocol)" + save_rules +} + +function list_rules() { + echo "" + echo "========== 当前的 NAT 转发规则 ==========" + nft -a list table ip nat 2>/dev/null || echo "当前没有任何 NAT 规则。" + echo "=========================================" +} + +function del_rule() { + list_rules + echo "" + echo "提示: 删除规则需要提供上方输出中的链名称 (chain) 和句柄编号 (handle)。" + read -p "请输入所在链的名称 (例如 prerouting 或 postrouting): " chain_name + read -p "请输入要删除的 rule handle 编号: " handle_num + + if [[ -n "$chain_name" && -n "$handle_num" ]]; then + nft delete rule ip nat $chain_name handle $handle_num + if [ $? -eq 0 ]; then + echo "规则 (handle $handle_num) 已删除。" + save_rules + else + echo "错误: 删除失败,请检查链名和句柄编号是否正确。" + fi + else + echo "输入无效,操作取消。" + fi +} + +function main() { + while true; do + echo "" + echo "===================================" + echo " nftables 端口转发管理脚本 " + echo "===================================" + echo "1. 添加端口转发规则" + echo "2. 查看当前转发规则" + echo "3. 删除特定转发规则" + echo "4. 退出脚本" + echo "===================================" + read -p "请选择一个操作 [1-4]: " option + + case $option in + 1) add_rule ;; + 2) list_rules ;; + 3) del_rule ;; + 4) + echo "退出脚本..." + exit 0 + ;; + *) + echo "无效的选项,请重新选择。" + ;; + esac + done +} + +main