gpt-4o 写的,我润色润色,好笑的是找了一万种解决方案,结果最后 AI 写的是唯一正常工作的

    Openwrt 24.10.1

    这次用 nf 桌子,首先检查下有没有 nat 表:

    nft list table nat

    如果输出显示了 nat 表和里面的链(如 PREROUTINGPOSTROUTING),说明已经有了,不然就新建一个:

    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_ipport

    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