购买了 IPLC 中转服务器,用于加速代理速度,可以借助 nftables 来做简单的 NAT 转发
因为 nftables 本身就集成在 Linux 内核中,无需额外安装,且性能优异
无需担心协议被识别的问题,NAT 转发只会修改 IP 和端口,不会改变数据包的内容,加密依旧是加密,只要你的代理协议本身足够隐蔽即可
数据包依旧在本地加密,在落地端解密,中间的 IPLC 机器不会看到任何明文数据(运营商和 IPLC 服务商也看不到)
为了方便添加多个落地加速,撰写一个脚本用于方便添加新的中转服务,内容如下:
#!/bin/bash
# NAT 转发管理
set -e
NFT="/usr/sbin/nft"
TABLE="natmgr"
CONFIG_FILE="/etc/nftables-natmgr.conf"
need_cmd() {
command -v "$1" >/dev/null 2>&1 || { echo "缺少命令: $1"; exit 1; }
}
need_cmd "$NFT"
if [[ $EUID -ne 0 ]]; then
echo "请使用 root 权限运行。"
exit 1
fi
init_table() {
if ! $NFT list table ip $TABLE >/dev/null 2>&1; then
echo "[+] 创建表 $TABLE 和必要的链"
$NFT add table ip $TABLE
$NFT add chain ip $TABLE prerouting { type nat hook prerouting priority -100\; }
$NFT add chain ip $TABLE postrouting { type nat hook postrouting priority 100\; }
# 虽然 forward 一般放在 filter 表,但这里保留你的设计
$NFT add chain ip $TABLE forward { type filter hook forward priority 0\; }
fi
}
save_rules() {
echo "#!/usr/sbin/nft -f" > "$CONFIG_FILE"
$NFT list table ip $TABLE >> "$CONFIG_FILE"
echo "[*] 规则已保存到 $CONFIG_FILE"
}
show_rules() {
echo ""
echo "============== 当前 NAT 转发情况 =============="
local rules
rules=$($NFT list chain ip $TABLE forward 2>/dev/null | grep -E 'comment "NAT-[0-9]+-.*"' || true)
if [[ -z "$rules" ]]; then
echo "暂无 NAT 转发规则"
echo "=============================================="
return
fi
local ports
ports=$(echo "$rules" | sed -n 's/.*comment "NAT-\([0-9]*\)-.*/\1/p' | sort -nu)
for port in $ports; do
local tcp_rule udp_rule rip rport packets bytes mb
tcp_rule=$(echo "$rules" | grep "comment \"NAT-${port}-tcp\"" | head -1)
if [[ -n "$tcp_rule" ]]; then
rip=$(echo "$tcp_rule" | grep -oE 'ip daddr [0-9.]+' | awk '{print $3}')
rport=$(echo "$tcp_rule" | grep -oE 'dport [0-9]+' | awk '{print $2}')
packets=$(echo "$tcp_rule" | grep -oE 'packets [0-9]+' | awk '{print $2}' || echo "0")
bytes=$(echo "$tcp_rule" | grep -oE 'bytes [0-9]+' | awk '{print $2}' || echo "0")
mb=$(echo "scale=2; $bytes/1024/1024" | bc -l 2>/dev/null || echo "0.00")
echo "本地端口 ${port}/tcp → ${rip}:${rport} (${mb} MB, ${packets} 包)"
fi
udp_rule=$(echo "$rules" | grep "comment \"NAT-${port}-udp\"" | head -1)
if [[ -n "$udp_rule" ]]; then
rip=$(echo "$udp_rule" | grep -oE 'ip daddr [0-9.]+' | awk '{print $3}')
rport=$(echo "$udp_rule" | grep -oE 'dport [0-9]+' | awk '{print $2}')
packets=$(echo "$udp_rule" | grep -oE 'packets [0-9]+' | awk '{print $2}' || echo "0")
bytes=$(echo "$udp_rule" | grep -oE 'bytes [0-9]+' | awk '{print $2}' || echo "0")
mb=$(echo "scale=2; $bytes/1024/1024" | bc -l 2>/dev/null || echo "0.00")
echo "本地端口 ${port}/udp → ${rip}:${rport} (${mb} MB, ${packets} 包)"
fi
done
echo "=============================================="
}
del_rule() {
local lport=$1
echo "[*] 删除端口 $lport 相关规则"
local deleted=0
for chain in prerouting postrouting forward; do
# -a 输出带 handle
local handles
# 只匹配前缀 NAT-<port>- 避免 80/8080 交叉
handles=$($NFT -a list chain ip $TABLE "$chain" 2>/dev/null | \
awk -v p="NAT-"$lport"-" '
/comment/ && $0 ~ p {
for(i=1;i<=NF;i++){
if($i=="handle"){print $(i+1)}
}
}' || true)
if [[ -n "$handles" ]]; then
for h in $handles; do
$NFT delete rule ip $TABLE "$chain" handle "$h" 2>/dev/null || true
echo "[-] 删除 $chain 链规则 handle $h"
deleted=$((deleted+1))
done
fi
done
if [[ $deleted -eq 0 ]]; then
echo "[-] 未找到端口 $lport 的相关规则"
else
echo "[*] 共删除 $deleted 条规则"
save_rules
fi
}
add_rule() {
local lport=$1
local remote=$2
local rip=${remote%%:*}
local rport=${remote##*:}
if [[ -z "$rip" || -z "$rport" ]]; then
echo "目标格式错误,应为 IP:PORT"
exit 1
fi
echo "[+] 添加规则: $lport → $rip:$rport"
del_rule "$lport"
# PREROUTING DNAT
$NFT add rule ip $TABLE prerouting tcp dport $lport dnat to $rip:$rport comment "NAT-${lport}-tcp-preroute"
$NFT add rule ip $TABLE prerouting udp dport $lport dnat to $rip:$rport comment "NAT-${lport}-udp-preroute"
# POSTROUTING MASQUERADE
$NFT add rule ip $TABLE postrouting ip daddr $rip masquerade comment "NAT-${lport}-post"
# FORWARD
$NFT add rule ip $TABLE forward ip daddr $rip tcp dport $rport counter accept comment "NAT-${lport}-tcp"
$NFT add rule ip $TABLE forward ip daddr $rip udp dport $rport counter accept comment "NAT-${lport}-udp"
save_rules
echo "[+] 规则添加完成"
show_rules
}
cleanup_rules() {
echo "[*] 清理重复规则..."
local ports
ports=$($NFT list chain ip $TABLE forward 2>/dev/null | \
grep -oE 'comment "NAT-[0-9]+-tcp"' | \
sed -n 's/comment "NAT-\([0-9]*\)-tcp"/\1/p' | sort -nu || true)
local cleaned=0
for port in $ports; do
local tcp_count udp_count
tcp_count=$($NFT list chain ip $TABLE forward 2>/dev/null | grep -c "comment \"NAT-${port}-tcp\"" || echo 0)
udp_count=$($NFT list chain ip $TABLE forward 2>/dev/null | grep -c "comment \"NAT-${port}-udp\"" || echo 0)
if [[ $tcp_count -gt 1 || $udp_count -gt 1 ]]; then
echo "[*] 清理端口 $port 的重复规则 (TCP:$tcp_count UDP:$udp_count)"
# 获取目标
local rule_info rip rport
rule_info=$($NFT list chain ip $TABLE forward 2>/dev/null | grep "comment \"NAT-${port}-tcp\"" | head -1)
rip=$(echo "$rule_info" | grep -oE 'ip daddr [0-9.]+' | awk '{print $3}')
rport=$(echo "$rule_info" | grep -oE 'dport [0-9]+' | awk '{print $2}')
if [[ -n "$rip" && -n "$rport" ]]; then
del_rule "$port"
add_rule "$port" "$rip:$rport"
cleaned=$((cleaned+1))
fi
fi
done
if [[ $cleaned -eq 0 ]]; then
echo "[*] 没有发现重复规则"
else
echo "[+] 清理了 $cleaned 个端口的重复规则"
fi
show_rules
}
list_all() {
echo "============== 详细规则列表 =============="
echo ""
echo "--- PREROUTING 链 ---"
$NFT list chain ip $TABLE prerouting 2>/dev/null | grep -E "(dnat|comment)" || echo "无规则"
echo ""
echo "--- POSTROUTING 链 ---"
$NFT list chain ip $TABLE postrouting 2>/dev/null | grep -E "(masquerade|comment)" || echo "无规则"
echo ""
echo "--- FORWARD 链 ---"
$NFT list chain ip $TABLE forward 2>/dev/null | grep -E "(counter|comment)" || echo "无规则"
echo "========================================"
}
reset_all() {
echo "[!] 警告:这将删除所有 NAT 规则!"
read -r -p "确认继续?(y/N): " confirm
if [[ "$confirm" == [yY] ]]; then
$NFT delete table ip $TABLE 2>/dev/null || echo "[*] 表不存在或已删除"
init_table
save_rules
echo "[+] 所有规则已清空"
else
echo "[*] 操作已取消"
fi
}
show_help() {
cat <<EOF
NAT 转发管理脚本 (纯 nftables 版本 - 修复版)
用法:
$0 show 显示当前 NAT 转发情况
$0 add <LOCAL_PORT> <IP:PORT> 添加 NAT 转发规则
$0 del <LOCAL_PORT> 删除 NAT 转发规则
$0 cleanup 清理重复规则
$0 list-all 显示所有规则详情
$0 reset 重置所有规则
示例:
$0 add 8080 192.168.1.100:80 # 将本地8080转发到192.168.1.100:80
$0 del 8080 # 删除8080端口的转发规则
EOF
}
init_table
case "$1" in
show)
show_rules
;;
add)
if [[ $# -ne 3 ]]; then
echo "错误:参数不足"
show_help
exit 1
fi
add_rule "$2" "$3"
;;
del)
if [[ $# -ne 2 ]]; then
echo "错误:参数不足"
show_help
exit 1
fi
del_rule "$2"
show_rules
;;
cleanup)
cleanup_rules
;;
list-all)
list_all
;;
reset)
reset_all
;;
*)
show_help
exit 1
;;
esac
使用上非常简单,假设脚本名为 add-nat.sh
,赋予可执行权限:
chmod +x add-nat.sh
然后执行以下命令:
# 添加转发规则,将本地 8080 端口转发到 1.2.3.4:1234
add-nat.sh add 8080 1.2.3.4:1234
# 删除转发规则,删除本地 8080 端口的转发
add-nat.sh del 8080
# 查看当前转发情况
add-nat.sh show
# 清理重复规则
add-nat.sh cleanup
# 显示所有规则详情
add-nat.sh list-all
# 重置所有规则
add-nat.sh reset