问题背景
上篇博文介绍了如何使用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+R → shell:startup 中创建了快捷方式,目标是:
arduino
powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File "C:\Scripts\wg-firewall-fix.ps1"
结果却让人大跌眼镜:重启电脑后,脚本文件被记事本打开了,根本没有执行!
问题排查
现象一:脚本被"打开"而不是"执行"
经过仔细检查,发现了几个可能的原因:
-
快捷方式配置错误
虽然设置了目标是
powershell.exe,但实际上可能只填了脚本路径,漏掉了前面的 PowerShell 命令参数。 -
文件关联问题
.ps1文件的默认关联程序是记事本(用于编辑),如果直接放入启动文件夹而不是创建快捷方式,Windows 会按照默认关联打开它。 -
文件扩展名误导
放入
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输出:方便调试
第二步:创建任务计划
-
打开任务计划程序
按
Win + S或者底部任务栏搜索,搜索任务计划程序(Task Scheduler)并打开 -
创建任务
点击右侧的 "创建任务..."(注意:不是"创建基本任务")
-
配置"常规"选项卡
- 名称:
WG-Firewall-Fix - 勾选"使用最高权限运行"(这是关键!)
- 配置:选择
Windows 10或Windows 11
- 名称:
-
配置"触发器"选项卡
- 点击"新建..."
- 开始任务:选择 "登录时"
- 设置:选择"特定用户"(你的账号)
- 点击"确定"
-
配置"操作"选项卡
-
点击"新建..."
-
操作:选择"启动程序"
-
程序或脚本:
powershell.exe -
添加参数:
arduino-ExecutionPolicy Bypass -WindowStyle Hidden -File "C:\Scripts\wg-firewall-fix.ps1" -
点击"确定"
-
-
配置"条件"选项卡
- 取消勾选"只有在计算机使用交流电源时才启动此任务"
(否则笔记本用电池时不会运行)
- 取消勾选"只有在计算机使用交流电源时才启动此任务"
-
保存任务
点击"确定",可能需要输入开机密码
第三步:清理旧的启动项
- 按
Win + R,输入shell:startup,回车 - 删除之前创建的 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] 脚本执行完毕
手动测试任务
在任务计划程序中:
- 找到
WG-Firewall-Fix任务 - 右键点击 → "运行"
- 查看日志确认执行成功
常见问题 FAQ
Q1: 任务执行后显示"0x1"错误代码
A: 这通常表示脚本执行失败。检查:
- 脚本路径是否正确
- 是否勾选了"使用最高权限运行"
- 查看日志文件中的具体错误信息
Q2: 笔记本用电池时不执行
A: 在"条件"选项卡中,取消勾选"只有在计算机使用交流电源时才启动此任务"
Q3: 想延迟执行怎么办?
A: 在脚本开头增加延迟:
powershell
Start-Sleep -Seconds 30 # 延迟30秒
或者在任务计划程序的触发器中设置"延迟任务时间"
Q4: 能否在关机时执行清理脚本?
A: 可以!创建另一个任务,触发器选择"注销时"或"关机时"
总结
通过任务计划程序,我们成功解决了两个核心问题:
- 权限问题:通过"使用最高权限运行",脚本可以执行需要管理员权限的命令
- 可靠性问题:任务计划程序比启动文件夹更稳定,支持日志记录和错误处理
关键要点:
- 涉及系统配置的脚本必须使用管理员权限
- 启动文件夹不适合运行需要提权的脚本
- 任务计划程序是 Windows 自动化任务的最佳选择
- 始终添加日志记录,方便排查问题
现在,每次开机后,WireGuard 防火墙规则和 WSL2 端口转发都会自动配置完成,再也不用手动干预启动了!