Windows下 DDNS会获取到已失效IP地址的解决方案

建站运维 Feb 15, 2026

家庭宽带下 IPV6公网地址经常由于运营商等原因被弃用,这时我们可以使用DDNS解决。

但Windows会因为传输稳定等考虑,不会立刻弃用IPV6地址,这就造成了IPconfig可以查到那个地址,但是在公网的IPV6ping服务已经无法ping通这个地址。

我们只需要一个简单的脚本,定期监测被标记为被废弃的地址,并立即清除即可。

禁止在生产环境中使用,这样会导致长连接的中断!


# --- 自动提权代码开始 ---
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
if (-not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    $arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`""
    Start-Process pwsh.exe -ArgumentList $arguments -Verb RunAs
    exit
}
# --- 自动提权代码结束 ---

# 这里放你原本的脚本逻辑
Write-Host "正在以管理员身份刷新 IPv6..."

# 2. 隐藏窗口逻辑 (针对已经提权后的进程)
# 这一段调用 Windows API 来彻底隐藏当前运行的窗口
$showWindowAsync = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'
$type = Add-Type -MemberDefinition $showWindowAsync -Name "Win32ShowWindowAsync" -Namespace "Win32" -PassThru
$hwnd = (Get-Process -Id $PID).MainWindowHandle
if ($hwnd -ne [IntPtr]::Zero) {
    # 0 代表 SW_HIDE (隐藏)
    $type::ShowWindowAsync($hwnd, 0)
}


# 获取桌面路径
$DesktopPath = [Environment]::GetFolderPath("Desktop")
$LogFile = "$DesktopPath\IPv6_Switch_Log.txt"

# 设置检测频率(秒)
$Interval = 5

Write-Host "------------------------------------------------" -ForegroundColor Cyan
Write-Host "IPv6 僵尸地址清理监控已启动..." -ForegroundColor Cyan
Write-Host "监控频率: 每 $Interval 秒一次"
Write-Host "日志路径: $LogFile"
Write-Host "提示: 如果检测到废弃地址,将在此处和桌面日志同步输出。"
Write-Host "------------------------------------------------" -ForegroundColor Cyan

while ($true) {
    try {
        # 1. 扫描所有状态为 Deprecated (弃用) 的 240x 开头公网 IPv6
        $Zombies = Get-NetIPAddress -AddressFamily IPv6 -ErrorAction SilentlyContinue | 
                   Where-Object { 
                       ($_.IPAddress -match "^240") -and 
                       ($_.AddressState -eq "Deprecated") 
                   }

        if ($Zombies) {
            foreach ($OldIP in $Zombies) {
                # 2. 寻找同一个接口上的接班人 (Preferred IP)
                $NewIPObj = Get-NetIPAddress -AddressFamily IPv6 -InterfaceIndex $OldIP.InterfaceIndex -AddressState Preferred -ErrorAction SilentlyContinue | 
                            Where-Object { $_.IPAddress -match "^240" } | 
                            Select-Object -First 1
                
                $NewIPStr = if ($NewIPObj) { $NewIPObj.IPAddress } else { "未检测到新IP" }
                $TimeStr = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
                $InterfaceName = $OldIP.InterfaceAlias

                # 3. 构造输出信息
                $LogContent = "[$TimeStr] 发生切换 | 接口: $InterfaceName | 废弃旧IP: $($OldIP.IPAddress) | 启用新IP: $NewIPStr"

                # --- 屏幕输出 (彩色) ---
                Write-Host "`n[!] 检测到地址废弃!" -ForegroundColor Yellow
                Write-Host "时间: $TimeStr"
                Write-Host "网卡: $InterfaceName"
                Write-Host "清理: $($OldIP.IPAddress)" -ForegroundColor Red
                Write-Host "新推: $NewIPStr" -ForegroundColor Green

                # --- 写入桌面日志 ---
                Add-Content -Path $LogFile -Value $LogContent -Encoding UTF8

                # 4. 执行清理
                Remove-NetIPAddress -InputObject $OldIP -Confirm:$false -ErrorAction SilentlyContinue
                
                # 刷新 DNS 缓存
                Clear-DnsClientCache
                Write-Host "清理完成,网络栈已刷新。" -ForegroundColor Gray
            }
        }
    }
    catch {
        # 保持静默不死
    }

    Start-Sleep -Seconds $Interval
}

Tags