OpenWrt PPPoE 自动检测 CGNAT 并重拨

admin
2026-03-31 / 0 评论 / 1 阅读 / 正在检测是否收录...

OpenWrt PPPoE 自动检测 CGNAT 并重拨(精简版 v3)

适用于:PPPoE 拨号用户
目标:避免获取 100.x.x.x(CGNAT)IP
特点:只检测 WAN IP,无公网出口检测,适合配合 OpenClash 使用

🚀 功能特点

  • ✅ 自动检测 WAN IP 是否为私网 / CGNAT
  • ✅ Hotplug 实时触发(ifup + ifupdate
  • ✅ Cron 定时兜底
  • ✅ 防死循环(最大重试次数)
  • ✅ 防并发(文件锁)
  • ✅ 冷却时间,避免频繁重拨
  • ✅ 日志清晰

🧩 一、主脚本

路径:

/root/wan_auto_redial.sh

内容:

#!/bin/sh

# ====== 锁(防并发)======
LOCK_FILE="/tmp/wan_redial.lock"
exec 200>$LOCK_FILE
flock -n 200 || {
    logger -t WAN-REDIAL "Another instance is running, exit"
    exit 0
}

# ====== 配置 ======
INTERFACE="wan"
MAX_RETRY=3
COOLDOWN=60   # 重拨最小间隔(秒)

COUNT_FILE="/tmp/wan_redial_count"
LAST_REDIAL_TIME_FILE="/tmp/last_redial_time"

# ====== 获取当前时间 ======
NOW=$(date +%s)

# ====== 冷却机制 ======
LAST_TIME=$(cat $LAST_REDIAL_TIME_FILE 2>/dev/null || echo 0)
if [ $((NOW - LAST_TIME)) -lt $COOLDOWN ]; then
    logger -t WAN-REDIAL "Cooldown active, skip"
    exit 0
fi

# ====== 获取WAN IP ======
WAN_IP=$(ubus call network.interface.$INTERFACE status | jsonfilter -e '@["ipv4-address"][0].address')

logger -t WAN-REDIAL "WAN IP: $WAN_IP"

[ -z "$WAN_IP" ] && exit 0

# ====== 判断私网IP(CGNAT) ======
is_private_ip() {
    echo "$1" | grep -qE '^(100\.|10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)'
}

NEED_REDIAL=0
if is_private_ip "$WAN_IP"; then
    logger -t WAN-REDIAL "Detected private/CGNAT IP, will redial"
    NEED_REDIAL=1
fi

# ====== 重拨逻辑 ======
if [ "$NEED_REDIAL" -eq 1 ]; then

    COUNT=$(cat $COUNT_FILE 2>/dev/null || echo 0)

    if [ "$COUNT" -lt "$MAX_RETRY" ]; then
        COUNT=$((COUNT+1))
        echo $COUNT > $COUNT_FILE
        echo $NOW > $LAST_REDIAL_TIME_FILE

        logger -t WAN-REDIAL "Redial attempt $COUNT/$MAX_RETRY..."

        ifdown $INTERFACE
        sleep 5
        ifup $INTERFACE
    else
        logger -t WAN-REDIAL "Max retries reached, stop redial"
    fi

else
    # 正常 WAN IP → 重置计数
    echo 0 > $COUNT_FILE
    logger -t WAN-REDIAL "WAN IP OK, no redial needed"
fi

🔧 二、赋予执行权限

chmod +x /root/wan_auto_redial.sh

⚡ 三、Hotplug 触发

路径:

/etc/hotplug.d/iface/99-wan-redial

内容:

#!/bin/sh

[ "$INTERFACE" = "wan" ] || exit 0
[ "$ACTION" = "ifup" -o "$ACTION" = "ifupdate" ] || exit 0

logger -t WAN-REDIAL "Hotplug triggered: ACTION=$ACTION"

/root/wan_auto_redial.sh

权限:

chmod +x /etc/hotplug.d/iface/99-wan-redial

⏱️ 四、Cron 兜底(5分钟一次)

crontab -e

添加:

*/5 * * * * /root/wan_auto_redial.sh

📊 五、日志查看

查看日志:

logread | grep WAN-REDIAL

实时查看:

logread -f | grep WAN-REDIAL

🧠 六、工作流程

拨号成功 / WAN IP 变化
   ↓
hotplug 触发(ifup / ifupdate)
   ↓
脚本执行(带锁)
   ↓
检测 WAN IP 是否私网
   ↓
满足条件 → 执行 ifdown/ifup 重拨
   ↓
最多 3 次 + 冷却控制

✅ 七、特性总结(精简版)

  • 只检查 WAN IP 是否私网(100.x / 10.x / 172.16-31 / 192.168.x)
  • 冷却机制防止频繁重拨
  • 最大 3 次重拨防死循环
  • Hotplug + Cron 双触发,保证稳定性
  • 文件锁防止并发执行
  • 适合 OpenClash 出口管理

备注:公网 IP 检测已去掉,所有判断基于 WAN IP 本地信息即可。
0

评论 (0)

取消