gpt-4o
写的,我润色润色,好笑的是找了一万种解决方案,结果最后 AI 写的是唯一正常工作的
Openwrt 24.10.1
这次用 nf 桌子,首先检查下有没有 nat
表:
nft list table nat
如果输出显示了 nat
表和里面的链(如 PREROUTING
、POSTROUTING
),说明已经有了,不然就新建一个:
nft add table nat
nft add chain nat PREROUTING { type nat hook prerouting priority 0 \; }
nft add chain nat POSTROUTING { type nat hook postrouting priority 100 \; }
然后就是老生常谈的脚本了。其他的可以参考后面的部分,这次是放开了所有端口
#!/bin/ash
# 配置区
INTERNAL_IP="192.168.31.2" # 内网服务器IP
IP_FILE="/etc/TigerBeanst/last_public_ip" # 存储上次公网IP的文件路径
# 获取当前公网IP(使用双源校验)
get_public_ip() {
local ip1
ip1=$(curl -4 -s --connect-timeout 5 http://4.ipw.cn || echo "N/A")
# ip2=$(curl -4 -s --connect-timeout 5 http://ipv4.ip.sb || echo "N/A")
if echo "$ip1" | grep -Eq '^([0-9]{1,3}\.){3}[0-9]{1,3}$'; then
echo "$ip1"
else
echo "ERROR"
fi
}
# 删除旧规则函数
delete_rules() {
local old_ip="$1"
local internal_ip="$2"
# 删除PREROUTING链中匹配旧公网IP的DNAT规则
nft delete rule nat PREROUTING ip daddr "$old_ip" dnat || true
# 删除POSTROUTING链中匹配内网IP的MASQUERADE规则
nft delete rule nat POSTROUTING ip daddr "$internal_ip" masquerade || true
}
# 添加新规则函数
add_rules() {
local current_ip="$1"
local internal_ip="$2"
for proto in tcp udp; do
# 添加PREROUTING链的DNAT规则
nft add rule nat PREROUTING ip daddr "$current_ip" ip protocol "$proto" dnat to "$internal_ip"
# 添加POSTROUTING链的MASQUERADE规则
nft add rule nat POSTROUTING ip daddr "$internal_ip" ip protocol "$proto" masquerade
done
}
# 主程序
CURRENT_IP=$(get_public_ip)
LAST_IP=$(cat "$IP_FILE" 2>/dev/null || echo "NONE")
if [ "$CURRENT_IP" = "ERROR" ]; then
echo "获取公网IP失败,保持现有规则"
exit 1
fi
if [ "$CURRENT_IP" = "$LAST_IP" ]; then
echo "公网IP未变化($CURRENT_IP),无需更新"
exit 0
fi
echo "检测到公网IP变更:
旧IP: ${LAST_IP:-无}
新IP: $CURRENT_IP
开始更新防火墙规则..."
if [ "$LAST_IP" != "NONE" ] && [ -n "$LAST_IP" ]; then
delete_rules "$LAST_IP" "$INTERNAL_IP"
echo "旧IP($LAST_IP)规则已清除"
fi
add_rules "$CURRENT_IP" "$INTERNAL_IP"
echo "$CURRENT_IP" > "$IP_FILE"
echo "新规则设置完成,当前生效IP: $CURRENT_IP"
Openwrt 23.05
创建回环配置脚本
因为对我来说,我所有在外部访问的服务实际会通过子域名区分,在内网被反向代理,所以我只需要配置一个端口就行,有多个的话应该依葫芦画瓢就行
注意修改 internal_ip
和 port
cat << 'EOF' > /etc/nat-loopback.sh
#!/bin/sh
# Get current public IP
public_ip=$(curl -s 4.ipw.cn)
# Internal server IP and port
internal_ip="192.168.31.1"
port="66666"
# Flush existing rules to avoid duplication
iptables -t nat -F PREROUTING
iptables -t nat -F POSTROUTING
iptables -F FORWARD
# Add NAT loopback rules
iptables -t nat -A PREROUTING -d $public_ip -j DNAT --to-destination $internal_ip
iptables -t nat -A POSTROUTING -s $internal_ip -j MASQUERADE
iptables -A FORWARD -d $internal_ip -p tcp --dport $port -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
EOF
然后授予运行权限
chmod +x /etc/nat-loopback.sh
防火墙模块
这一步不一定需要,但可能会因为缺模块导致无法工作,如果直接运行 /etc/nat-loopback.sh
没问题,就没必要走这一步
opkg update
opkg install ip-full iptables-mod-extra kmod-ipt-nat kmod-ipt-extra kmod-ipt-conntrack kmod-nf-conntrack
安装完后重启防火墙
/etc/init.d/firewall restart
测试
直接执行这个指令文件就行
/etc/nat-loopback.sh
如果没有报错,就尝试访问之前因为没有配置好环回导致出问题的地址,如果也正常,就可以把这个指令加到计划任务里了(因为涉及到获取公网IP,你要是买的固定IP算我没说)
*/5 * * * * /etc/nat-loopback.sh
Openwrt 18.06
依葫芦画瓢,缺一些模块的话自己上网找下
#!/bin/sh
# NAT Loopback Variables
INTERNAL_IP="192.168.31.1"
PORT="6666"
CURRENT_IP=$(curl -s http://4.ipw.cn)
# Check if PUBLIC_IP variable is set
if [ -z "$PUBLIC_IP" ]; then
PUBLIC_IP=$CURRENT_IP
fi
echo "Current IP: $CURRENT_IP"
echo "Public IP: $PUBLIC_IP"
echo "Updating NAT loopback rules"
# Clear existing NAT loopback rules
iptables -t nat -D PREROUTING -d $PUBLIC_IP -p tcp --dport $PORT -j DNAT --to-destination $INTERNAL_IP:$PORT 2>/dev/null
iptables -t nat -D POSTROUTING -d $INTERNAL_IP -p tcp --dport $PORT -j MASQUERADE 2>/dev/null
# Update PUBLIC_IP
PUBLIC_IP=$CURRENT_IP
# Add updated NAT loopback rules
iptables -t nat -A PREROUTING -d $PUBLIC_IP -p tcp --dport $PORT -j DNAT --to-destination $INTERNAL_IP:$PORT
iptables -t nat -A POSTROUTING -d $INTERNAL_IP -p tcp --dport $PORT -j MASQUERADE
# Verify rules
# echo "Current iptables rules:"
# iptables -t nat -L -v -n
yoshiki Chrome 128.0.0.0
试了好多种办法,你这个成功了,感谢!
ssj Chrome 131.0.0.0
本来我也想尝试这个方法的, 问了gpt这段代码的原理后, 自己稍加思考, 不用代码也能实现, 我是卡在内网和外网使用相同的域名都可以访问到内部服务的问题,外网域名访问的问题已经解决了, 要解决内网也使用域名访问, 在openwrt的端口转发的地方:之前是lan转到wan,现在新增一条wan转到lan,启用nat回环,内部ip,Reflection zones设置为wan
TigerBeanst Edge Chromium 131.0.0.0
我最开始也是单纯设置区域,但没成功hhh