# 如何透過 PowerShell 快速建立 Windows 內建 VPN 連線並自動記憶密碼連線

有鑑於近日台灣 [COVID-19 疫情](https://www.ftvnews.com.tw/topics/COVID-19/index.html) 相當嚴峻，政府也在前幾日宣布[全台疫情警戒升第三級](https://www.cna.com.tw/news/firstnews/202105195009.aspx)，我們公司也在 2021/5/17 開始全員在家上班，以致於使用 VPN 的同仁暴增，進而也遇到許多連線問題。本篇文章我要來分享幾個快速建立 VPN 的 PowerShell 命令，幫助大家在不瞭解 VPN 背景知識的情況下，也能快速且正確的設定好 VPN 連線。

### 快速設定 VPN 連線

以下是我們公司用來快速建立 VPN 連線的 PowerShell 指令碼，請**以系統管理人員身份**開啟執行：

```powershell
$VPNProfile = "MyVPN"

$VPNServer = "IP.Address"
$DNSSuffix = "AD.Domain"
$L2tpPsk   = "L2TP 的 Pre-shared key (PSK)"

Add-VpnConnection -Name $VPNProfile -AllUserConnection -ServerAddress $VPNServer -TunnelType L2tp -L2tpPsk $L2tpPsk -DnsSuffix $DNSSuffix -Force -RememberCredential
```

> 🔥 注意: 這裡加上 `-AllUserConnection` 是關鍵設定！

以下是幾個重要參數的說明：

1.  為了將 VPN 連線註冊到**全域的電話簿** (global phone book)，所以我們要加上 `-AllUserConnection` 參數！
2.  由於我們公司的 VPN 採用 L2TP ([Layer 2 Tunneling Protocol](https://en.wikipedia.org/wiki/Layer_2_Tunneling_Protocol)) 協定進行連線，所以必須指定正確的 Pre-shared key (`PSK`) 才能成功連線，因此需要加上 `-L2tpPsk $L2tpPsk` 才行，這個參數只有在使用 `-TunnelType L2tp` 的時候才能用。
3.  我們公司的網路有透過 Active Directory (AD) 進行管理，所以加上預設 DNS 尾碼會比較方便，所以加上 `-DnsSuffix $DNSSuffix` 參數。
4.  當你第一次登入 VPN 之後，如果想要**記憶密碼**，可以加上 `-RememberCredential` 參數。
5.  如果你的 `PSK` 會透過**不安全的頻道**傳送，必須加上 `-Force` 才能設定成功。

> 完整的參數說明請看 [Add-VpnConnection (VpnClient) | Microsoft Docs](https://learn.microsoft.com/en-us/powershell/module/vpnclient/add-vpnconnection?view=windowsserver2019-ps&WT.mc_id=DT-MVP-4015686) 文件。

### 關於 RAS 電話簿

我們經常會說 VPN 要用「撥接」的方式進行連線，這個概念自然來自於傳統的「電話簿」(Phone Book)，然後概念也確實一樣，我們上述建立 VPN 連線的過程，其實就是建立到 Windows 10 內建的 RAS ([Remote Access Services](https://en.wikipedia.org/wiki/Remote_access_service)) 電話簿中。

你可以執行 `rasphone` 命令（`C:\Windows\System32\rasphone.exe`）來啟動**網路連線**的視窗，而你從執行檔的名稱就可以看出這其實就是 RAS 電話簿 ([RAS Phone Books](https://learn.microsoft.com/en-us/windows/win32/rras/ras-phone-books?WT.mc_id=DT-MVP-4015686))！

![Network Connections (rasphone.exe)](https://stwillblogassets.blob.core.windows.net/files/images/external/user-images.githubusercontent.com/8e0ea0f21e16d49daecd-118953288-42f8de00-b98f-11eb-8aa5-13df1e389e26.jpg)

### 快速撥接 VPN 連線

我前幾年有寫過一篇 [如何透過命令提示字元快速連接 Windows 內建的 VPN 連線](/post/2019/02/12/Dial-up-VPN-connection-using-CLI-tool-rasdial) 文章，其中所使用到的工具程式 `rasdial.exe` 就是專門用來呼叫 RAS 電話簿中的網路連線。

如果你是使用 PowerShell 的 [Add-VpnConnection](https://learn.microsoft.com/en-us/powershell/module/vpnclient/add-vpnconnection?view=windowsserver2019-ps&WT.mc_id=DT-MVP-4015686) 新增的 VPN 連線，雖然可以透過 `rasphone` 可以看到這些連線設定，但是無法自動撥接出去，雖然可以記憶密碼，但你一定會看到以下畫面，只要按下 `Enter` 鍵就可以自動連線：

![image](https://stwillblogassets.blob.core.windows.net/files/images/external/user-images.githubusercontent.com/fc5d5506b0b94f77f86e-185749464-9b709cf3-6a9d-43b9-95a6-2dd9eb59564a.png)

會出現這個問題，就是因為你在透過 `Add-VpnConnection` 時，沒有加上 `-AllUserConnection` 參數的緣故。因為唯有加上 `-AllUserConnection` 才能將連線註冊到系統的 RAS 電話簿之中！ 🔥

### 撥接 VPN 時免輸入密碼的方法

我們可以使用 `rasdial.exe` 工具，幫助我們自動撥接 VPN 連線，以下就是進行特別設定的方法：

1.  請以**系統管理員權限**開啟 Notepad 或任意文字編輯器
    
    打開 `%ProgramData%\Microsoft\Network\Connections\Pbk\rasphone.pbk` 檔案
    
    > 注意: 此檔案為 `UTF-8` 編碼，如果你的 VPN 連線名稱有使用中文，可能會出現亂碼的情況，請記得使用正確的文字編碼開啟檔案。
    
2.  調整設定**無互動**自動撥接 VPN 連線的參數
    
    上一個步驟的 `rasphone.pbk` 檔案，其實是一個 `INI` 文字檔，如果你有設定兩個不同的 VPN 連線，那麼這個檔案就會有兩個區段設定，請記得要調整正確的參數。
    
    你必須找到一個 `PreviewUserPw=1` 參數，其值預設為 `1`，你必須把他改成 `0` 之後儲存檔案，才能進行下一步。
    
3.  執行 `rasphone -d "MyVPN"` 命令來撥接
    
    其中 `MyVPN` 是你在建立 VPN 連線時所指定的連線名稱！
    
    撥接 VPN 的過程中畫面會出現以下視窗，但是不會出現太久，當 VPN 連線成功後就會自動消失：
    
    ![Connecting to DuotifyVPN](https://stwillblogassets.blob.core.windows.net/files/images/external/user-images.githubusercontent.com/92f1052f456cce60522d-119266982-8d908980-bc1f-11eb-8e29-c38dcfea1f5b.jpg)
    

上述三個步驟都設定成功，就代表你已經可以**免密碼**自動撥接 VPN 了！

今後就只要執行以下命令就可以自動撥接/掛斷 VPN，而且還不用將**連線密碼**寫死在**批次檔**或 [AutoHotkey](https://www.autohotkey.com/) 的指令檔中：

-   撥接 VPN
    
    ```powershell
    rasphone -d "MyVPN"
    ```
    
-   掛斷 VPN
    
    ```powershell
    rasphone -h "MyVPN"
    ```
    

### 設定 AutoHotkey 自動連線

以下是我寫好的 [AutoHotkey](https://www.autohotkey.com/) 命令腳本：

1.  撥接 VPN ( 快速鍵: `Ctrl-Alt-Shift-V` )
    
    ```ahk
    ^!+v::
    RunWait, rasdial.exe VPNName, C:\Windows\System32, Hide|UseErrorLevel
    if (ErrorLevel) {
        TrayTip, 啟動 VPN 連線, 連線至 VPN 發生錯誤 (%A_LastError%), 3, 3
    } else {
        TrayTip, 啟動 VPN 連線, 成功連線至 VPN  (%A_LastError%), 3, 1
    }
    return
    ```
    
2.  掛斷 VPN ( 快速鍵: `Ctrl-Alt-Shift-D` )
    
    ```ahk
    ^!+d::
    RunWait, rasdial.exe VPNName /DISCONNECT, C:\Windows\System32, Hide|UseErrorLevel
    if (ErrorLevel) {
        TrayTip, 啟動 VPN 連線, 中斷 VPN 連線發生錯誤  (%A_LastError%), 3, 3
    } else {
        TrayTip, 啟動 VPN 連線, 已中斷 VPN 連線 (%A_LastError%), 3, 1
    }
    return
    ```
    

上述 AutoHotkey 腳本中，[TrayTip](https://www.autohotkey.com/docs/commands/TrayTip.htm) 命令會讓你連線成功或失敗時顯示通知訊息。

> 如果你是 Windows 10 用戶，且使用 TrayTip 完全沒效果，請用以下 Chocolatey 命令重新安裝 AutoHotkey 才會正常運作：
> 
> ```bash
> choco install autohotkey.install --params="'/DefaultVer:U32'"
> ```
> 
> 相關討論：[https://www.autohotkey.com/boards/viewtopic.php?p=261485#p261485](https://www.autohotkey.com/boards/viewtopic.php?p=261485#p261485)

### 相關連結

-   [設定預先共用金鑰，以搭配 Windows Server 2003 中的第2層隧道通訊協定連線使用](https://learn.microsoft.com/zh-tw/troubleshoot/windows-server/windows-security/configure-preshared-key-to-use-l2tp?WT.mc_id=DT-MVP-4015686)
-   [Add-VpnConnection (VpnClient) | Microsoft Docs](https://learn.microsoft.com/en-us/powershell/module/vpnclient/add-vpnconnection?view=windowsserver2019-ps&WT.mc_id=DT-MVP-4015686)
-   [networking - Single-Click to connet to VPN on Windows 10 - Super User](https://superuser.com/a/1027290/95798)
