# ============================================================ # MyBlog IP 白名单自动上报脚本(在家庭 Windows 电脑上运行) # 作用:读取当前公网 IP -> 与上次记录比较 -> 有变化就通知服务器 # 更新阿里云安全组 22 端口白名单(避免换 IP 后 SSH 连不上) # 用法: # 手动运行: powershell -ExecutionPolicy Bypass -File .\report.ps1 # 定时运行: 先运行 install.ps1(注册每 30 分钟执行一次的计划任务) # 退出码:0=成功(含无需更新) 1=配置错误 2=取IP失败 3=IP不合法 4=服务器拒绝 5=网络错误 # ============================================================ $ErrorActionPreference = "Stop" $ScriptDir = $PSScriptRoot $ConfFile = Join-Path $ScriptDir "ipwatch.conf" $LastFile = Join-Path $ScriptDir "lastip.txt" $LogFile = Join-Path $ScriptDir "ipwatch.log" # ---------- 1. 读取配置 ---------- $Server = "" $Secret = "" if (Test-Path -LiteralPath $ConfFile) { Get-Content -LiteralPath $ConfFile -Encoding UTF8 | ForEach-Object { $line = $_.Trim() if ($line -match '^SERVER\s*=\s*(.+)$') { $Server = $Matches[1].Trim().Trim('"') } elseif ($line -match '^SECRET\s*=\s*(.+)$') { $Secret = $Matches[1].Trim().Trim('"') } } } if (-not $Server -or -not $Secret) { Write-Host "配置不完整:请复制 ipwatch.conf.example 为 ipwatch.conf,并填写 SERVER 与 SECRET" -ForegroundColor Red exit 1 } # ---------- 2. 日志工具 ---------- function Write-Log([string]$message) { $line = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $message" try { Add-Content -LiteralPath $LogFile -Value $line -Encoding UTF8 } catch { } Write-Host $line } # ---------- 3. 获取当前公网 IP(走博客的 /myip 接口) ---------- # 旧系统默认不启用 TLS1.2,先强制开启,否则 HTTPS 请求会失败 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 try { $current = (Invoke-RestMethod -Uri "$Server/myip" -TimeoutSec 20).ToString().Trim() } catch { Write-Log "获取公网 IP 失败:$($_.Exception.Message)" exit 2 } if ($current -notmatch '^\d{1,3}(\.\d{1,3}){3}$') { Write-Log "服务器返回的不是合法 IP:$current" exit 3 } # ---------- 4. 与上次记录比较,没变化就不打扰服务器 ---------- $last = "" if (Test-Path -LiteralPath $LastFile) { $last = (Get-Content -LiteralPath $LastFile -Raw -Encoding UTF8).Trim() } if ($current -eq $last) { Write-Host "公网 IP 未变化:$current" exit 0 } # ---------- 5. IP 有变化:上报给服务器,由服务器更新安全组 ---------- try { $body = @{ secret = $Secret; ip = $current } | ConvertTo-Json $resp = Invoke-RestMethod -Uri "$Server/api/ipwatch/report" -Method Post -Body $body -ContentType "application/json; charset=utf-8" -TimeoutSec 40 if ($resp.success) { Set-Content -LiteralPath $LastFile -Value $current -Encoding UTF8 Write-Log "白名单更新成功:$current(服务器:$($resp.message))" exit 0 } else { Write-Log "服务器返回失败:$($resp.message)" exit 4 } } catch { Write-Log "上报失败:$($_.Exception.Message)" exit 5 }