PowerShell 开机脚本不执行?WireGuard 防火墙配置踩坑实录(接从零搭建安全内网穿透博文)

问题背景

上篇博文介绍了如何使用WireGuard反向代理访问家庭网络,但是最近在使用 WireGuard + WSL2 的过程中,遇到了一个棘手的问题:每次重启电脑后,都需要手动执行一系列命令来配置防火墙规则和端口转发,非常繁琐。

于是我写了一个 PowerShell 脚本来自动化这个过程:

powershell 复制代码
# 等待 WireGuard 完全连接
Start-Sleep -Seconds 20

# 找到 WireGuard 接口
$wg = Get-NetAdapter | Where-Object { $_.InterfaceDescription -like "*WireGuard*" -or $_.Name -like "*wg*" } | Select-Object -First 1
if (-not $wg) { exit 1 }

# 设置专用网络 + 创建精准规则
Set-NetConnectionProfile -InterfaceAlias $wg.Name -NetworkCategory Private -ErrorAction SilentlyContinue
Remove-NetFirewallRule -DisplayName "WSL2-SSH-2222" -ErrorAction SilentlyContinue
New-NetFirewallRule -DisplayName "WSL2-SSH-2222" -Direction Inbound -LocalPort 2222 -Protocol TCP -Action Allow -Profile Private -InterfaceAlias $wg.Name -Enabled True | Out-Null

# 重建 netsh
netsh interface portproxy delete v4tov4 listenport=2222 listenaddress=10.8.0.2 2>$null
netsh interface portproxy add v4tov4 listenport=2222 listenaddress=10.8.0.2 connectport=22 connectaddress=127.0.0.1

# 唤醒 WSL2
wsl -d Ubuntu -u root -e sh -c "exit" 2>$null

按照常规操作,我在 Win+Rshell:startup 中创建了快捷方式,目标是:

arduino 复制代码
powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File "C:\Scripts\wg-firewall-fix.ps1"

结果却让人大跌眼镜:重启电脑后,脚本文件被记事本打开了,根本没有执行!


问题排查

现象一:脚本被"打开"而不是"执行"

经过仔细检查,发现了几个可能的原因:

  1. 快捷方式配置错误

    虽然设置了目标是 powershell.exe,但实际上可能只填了脚本路径,漏掉了前面的 PowerShell 命令参数。

  2. 文件关联问题
    .ps1 文件的默认关联程序是记事本(用于编辑),如果直接放入启动文件夹而不是创建快捷方式,Windows 会按照默认关联打开它。

  3. 文件扩展名误导

    放入 shell:startup 的应该是一个 .lnk 快捷方式,而不是直接的 .ps1 文件。

现象二:即使执行了也会失败(致命问题!)

解决了"打开文件"的问题后,我发现了更严重的问题:脚本中的命令全部失败!

原因很简单:

powershell 复制代码
# 这些命令都需要管理员权限!
New-NetFirewallRule          # 防火墙规则
Set-NetConnectionProfile     # 网络配置
netsh interface portproxy    # 端口映射

shell:startup 中的脚本是以普通用户权限运行的,不会自动请求提权。 所以这些需要管理员权限的命令要么报错,要么静默失败。


终极解决方案:任务计划程序

Windows 提供了更强大的工具------任务计划程序,它可以:

  • 以管理员权限运行
  • 在登录时自动触发
  • 隐藏窗口执行
  • 记录执行日志

第一步:优化脚本(增加日志和权限检查)

首先,让我们改进脚本,增加错误处理和日志记录:

powershell 复制代码
# wg-firewall-fix.ps1
# 强制要求管理员权限
#Requires -RunAsAdministrator

# 启动日志记录,方便排查问题
$LogPath = "C:\Scripts\wg-fix-log.txt"
Start-Transcript -Path $LogPath -Append

Write-Host "[$(Get-Date)] 脚本开始执行..."

# 等待 WireGuard 完全连接(根据网络情况调整时间)
Start-Sleep -Seconds 20

# 找到 WireGuard 接口
$wg = Get-NetAdapter | Where-Object { 
    $_.InterfaceDescription -like "*WireGuard*" -or 
    $_.Name -like "*wg*" 
} | Select-Object -First 1

if (-not $wg) { 
    Write-Host "错误:未找到 WireGuard 网卡" 
    Stop-Transcript
    exit 1 
}

Write-Host "找到网卡:$($wg.Name)"

# 设置专用网络 + 创建精准规则
Set-NetConnectionProfile -InterfaceAlias $wg.Name -NetworkCategory Private -ErrorAction SilentlyContinue

# 删除旧规则
Remove-NetFirewallRule -DisplayName "WSL2-SSH-2222" -ErrorAction SilentlyContinue

# 创建新规则
New-NetFirewallRule -DisplayName "WSL2-SSH-2222" -Direction Inbound -LocalPort 2222 -Protocol TCP -Action Allow -Profile Private -InterfaceAlias $wg.Name -Enabled True | Out-Null
Write-Host "防火墙规则已设置"

# 重建 netsh 端口代理
netsh interface portproxy delete v4tov4 listenport=2222 listenaddress=10.8.0.2 2>$null
netsh interface portproxy add v4tov4 listenport=2222 listenaddress=10.8.0.2 connectport=22 connectaddress=127.0.0.1
Write-Host "Netsh 端口映射已设置"

# 唤醒 WSL2
wsl -d Ubuntu -u root -e sh -c "exit" 2>$null
Write-Host "WSL2 已唤醒"

Write-Host "[$(Get-Date)] 脚本执行完毕"
Stop-Transcript

关键改进点:

  • #Requires -RunAsAdministrator:强制要求管理员权限
  • Start-Transcript:记录执行日志到文件
  • 详细的 Write-Host 输出:方便调试

第二步:创建任务计划

  1. 打开任务计划程序

    Win + S或者底部任务栏搜索,搜索任务计划程序(Task Scheduler)并打开

  2. 创建任务

    点击右侧的 "创建任务..."(注意:不是"创建基本任务")

  3. 配置"常规"选项卡

    • 名称:WG-Firewall-Fix
    • 勾选"使用最高权限运行"(这是关键!)
    • 配置:选择 Windows 10Windows 11
  4. 配置"触发器"选项卡

    • 点击"新建..."
    • 开始任务:选择 "登录时"
    • 设置:选择"特定用户"(你的账号)
    • 点击"确定"
  5. 配置"操作"选项卡

    • 点击"新建..."

    • 操作:选择"启动程序"

    • 程序或脚本:powershell.exe

    • 添加参数:

      arduino 复制代码
      -ExecutionPolicy Bypass -WindowStyle Hidden -File "C:\Scripts\wg-firewall-fix.ps1"
    • 点击"确定"

  6. 配置"条件"选项卡

    • 取消勾选"只有在计算机使用交流电源时才启动此任务"
      (否则笔记本用电池时不会运行)
  7. 保存任务

    点击"确定",可能需要输入开机密码

第三步:清理旧的启动项

  1. Win + R,输入 shell:startup,回车
  2. 删除之前创建的 PowerShell 快捷方式,避免冲突

验证与调试

查看执行日志

脚本执行后,查看日志文件:

powershell 复制代码
# 查看最新日志
Get-Content C:\Scripts\wg-fix-log.txt -Tail 50

正常的日志应该类似:

vbnet 复制代码
**********************
Windows PowerShell 脚本开始
开始时间: 20260222133618
用户名: WIN-xxxxxxxxxxxxxx\Administrator
RunAs 用户: WIN-xxxxxxxxxxxxxx\Administrator
配置名称: 
计算机: WIN-xxxxxxxxxxxxxx (Microsoft Windows NT 10.0.22000.0)
主机应用程序: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
进程 ID: 8584
PSVersion: 5.1.22000.2538
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.22000.2538
BuildVersion: 10.0.22000.2538
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
已启动脚本,输出文件为 C:\Scripts\wg-fix-log.txt
PS C:\Users\Administrator> Write-Host "[$(Get-Date)] 脚本开始执行..."
[02/22/2026 13:36:18] 脚本开始执行...
PS C:\Users\Administrator> # 等待 WireGuard 完全连接 (根据你的网络情况调整时间)
PS C:\Users\Administrator> Start-Sleep -Seconds 20
PS C:\Users\Administrator> # 找到 WireGuard 接口
PS C:\Users\Administrator> $wg = Get-NetAdapter | Where-Object { $_.InterfaceDescription -like "*WireGuard*" -or $_.Name -like "*wg*" } | Select-Object -First 1
PS C:\Users\Administrator> if (-not $wg) { 
    Write-Host "错误:未找到 WireGuard 网卡" 
    Stop-Transcript
    exit 1 
}
PS C:\Users\Administrator> Write-Host "找到网卡:$($wg.Name)"
找到网卡:home
PS C:\Users\Administrator> # 设置专用网络 + 创建精准规则
PS C:\Users\Administrator> Set-NetConnectionProfile -InterfaceAlias $wg.Name -NetworkCategory Private -ErrorAction SilentlyContinue
PS C:\Users\Administrator> # 删除旧规则
PS C:\Users\Administrator> Remove-NetFirewallRule -DisplayName "WSL2-SSH-2222" -ErrorAction SilentlyContinue
PS C:\Users\Administrator> # 创建新规则
PS C:\Users\Administrator> New-NetFirewallRule -DisplayName "WSL2-SSH-2222" -Direction Inbound -LocalPort 2222 -Protocol TCP -Action Allow -Profile Private -InterfaceAlias $wg.Name -Enabled True | Out-Null
PS C:\Users\Administrator> Write-Host "防火墙规则已设置"
防火墙规则已设置
PS C:\Users\Administrator> # 重建 netsh 端口代理
PS C:\Users\Administrator> netsh interface portproxy delete v4tov4 listenport=2222 listenaddress=10.8.0.2 2>$null

PS C:\Users\Administrator> netsh interface portproxy add v4tov4 listenport=2222 listenaddress=10.8.0.2 connectport=22 connectaddress=127.0.0.1

PS C:\Users\Administrator> Write-Host "Netsh 端口映射已设置"
Netsh 端口映射已设置
PS C:\Users\Administrator> # 唤醒 WSL2
PS C:\Users\Administrator> wsl -d Ubuntu -u root -e sh -c "exit" 2>$null

PS C:\Users\Administrator> Write-Host "WSL2 已唤醒"
WSL2 已唤醒
PS C:\Users\Administrator> Write-Host "[$(Get-Date)] 脚本执行完毕"
[02/22/2026 13:36:43] 脚本执行完毕

手动测试任务

在任务计划程序中:

  1. 找到 WG-Firewall-Fix 任务
  2. 右键点击 → "运行"
  3. 查看日志确认执行成功

常见问题 FAQ

Q1: 任务执行后显示"0x1"错误代码

A: 这通常表示脚本执行失败。检查:

  • 脚本路径是否正确
  • 是否勾选了"使用最高权限运行"
  • 查看日志文件中的具体错误信息

Q2: 笔记本用电池时不执行

A: 在"条件"选项卡中,取消勾选"只有在计算机使用交流电源时才启动此任务"

Q3: 想延迟执行怎么办?

A: 在脚本开头增加延迟:

powershell 复制代码
Start-Sleep -Seconds 30  # 延迟30秒

或者在任务计划程序的触发器中设置"延迟任务时间"

Q4: 能否在关机时执行清理脚本?

A: 可以!创建另一个任务,触发器选择"注销时"或"关机时"


总结

通过任务计划程序,我们成功解决了两个核心问题:

  1. 权限问题:通过"使用最高权限运行",脚本可以执行需要管理员权限的命令
  2. 可靠性问题:任务计划程序比启动文件夹更稳定,支持日志记录和错误处理

关键要点:

  • 涉及系统配置的脚本必须使用管理员权限
  • 启动文件夹不适合运行需要提权的脚本
  • 任务计划程序是 Windows 自动化任务的最佳选择
  • 始终添加日志记录,方便排查问题

现在,每次开机后,WireGuard 防火墙规则和 WSL2 端口转发都会自动配置完成,再也不用手动干预启动了!

相关推荐
AC赳赳老秦4 小时前
2026多模态技术趋势预测:DeepSeek处理图文音视频多格式数据实战指南
java·人工智能·python·安全·架构·prometheus·deepseek
无心水5 小时前
【任务调度:数据库锁 + 线程池实战】4、架构实战:用线程池 + SKIP LOCKED 构建高可用分布式调度引擎
人工智能·分布式·后端·spring·架构
Max_uuc5 小时前
【架构心法】榨干 USB 带宽:多合一调试工具的“复合设备”架构与端点分配哲学
架构
Coder_Boy_6 小时前
Java高级_资深_架构岗 核心知识点(模块三:高并发)
java·spring boot·分布式·面试·架构
Coder_Boy_6 小时前
Java高级_资深_架构岗 核心知识点全解析(模块二:Spring生态 架构岗必备)
java·spring boot·spring·架构
Max_uuc7 小时前
【架构心法】驯服数据洪流:基于 Qt/QML 的多通道高频监控与 MVVM 解耦哲学
架构
岱宗夫up7 小时前
【前端基础】HTML + CSS + JavaScript 基础(二)
开发语言·前端·javascript·css·架构·前端框架·html
Coder_Boy_8 小时前
Java高级_资深_架构岗 核心知识点全解析(通俗透彻+理论+实践+最佳实践)
java·spring boot·分布式·面试·架构
倔强的石头1068 小时前
一卡通核心交易平台的国产数据库实践解析:架构、迁移与高可用落地
数据库·架构·kingbase