我的手機不知道在哪一年的更新之後,內建的 VPN 就只剩下 IKEv2/IPsec 這種方式了,又不知道在哪天我就開始想要自己架一個 VPN 伺服器,2024 年的寒假我就開始研究怎麼樣用 VPN 連線回家。
因為系統是 Linux,第一個在網路上找到的就是 strongSwan 這套軟體,然後又找了一下網路上的教學,但我照著教學不知道為什麼就是連線不了,憑證也是簽了又刪無數次。但我沒有因此放棄,我直接去看官方文件,官方的文件都是用 swanctl 設定檔的格式寫的,我本來還堅持用 strongSwan 的預設格式,因為網路上的教學撰寫的時間久遠,我最一開始接觸到的就是如此,但在試用之後才發現 swanctl 的設定檔更加的人性化,比原本的格式不知道好了多少。strongSwan 官方還給出了大部分設定的範例,應該百分之九十的情況都可以處理。
因此我決定寫一篇相對比較新的教學,也算是做個紀錄,給未來想要架設的人有個方向。
概要
以下是我自己整理的重點:
- IPsec 用於保護兩個節點之間的資料傳輸,使用 UDP 協議傳輸
- IPsec 在開始傳輸之前需要先進行金錀協商和身份驗證,而實作方法常見的有 L2TP 或 IKEv2,因此常常可以在手機看到 L2TP/IPsec 或 IKEv2/IPsec,而 strongSwan 提供的是 IKEv2/IPsec
- IKEv2 分為兩步
- 第一步兩個節點會協商出保護第二步的密鑰和後續必要的資訊
- 第二步會進行身份驗證及協商出 IPsec 的密鑰,此時的封包受到第一步協商出的密鑰加密
- 理論上不存在伺服端跟客戶端,但實際上還是會有一端當成伺服器
- 伺服端跟客戶端都需要設定驗證方式,只有在兩邊都驗證通過才能連線
- 驗證方式有憑證、EAP、PSK 三種,EAP 在易用性跟安全性上取得了平衡
- EAP 如果想要也可以用第三方伺服器驗證(RADIUS)
- 伺服器一般來說都會用憑證做為自身的憑證方式,手機版 strongSwan 客戶端也只能連線使用憑證驗證的伺服器
連接握手
下方使用設定如下:
- 伺服器為憑證驗證
- 客戶端為 EAP 驗證
IKEv2 握手有四步:
- 客戶端對伺服器握手
- 伺服器返回握手,如果有開啟憑證請求會在這一步傳送
- 客戶端返回對應的驗證方式,這裡是 EAP。若有開啟憑證請求也會一同傳送
- 伺服器返回憑證
- 在握手的前兩步雙方會協商出密鑰保護第三步和第四步
- 憑證請求的目地在於雙方皆可以設定不主動傳送憑證,若不主動傳送則需要憑證請求才能得到憑證
- 例如 Windows 或 strongSwan-network-manager 皆不會主動傳送憑證
- 憑證請求較消耗流量,可以自行決定是否開啟
架設
以下是我自己整理的重點:
- 如果使用 Docker 要開始 privileged 才能使用
- strongswan 需要在 ipsec 這個套件上面運作,在安裝 strongswan 的時候會自動連同 ipsec 一起安裝
- 新版的 strongswan 使用 swanctl 來管理各種設定,網路上有些教學使用僅 strongSwan 的設定檔,兩者功能相同
- 架設需要安裝套件,下方列出的套件皆可使用 apt 安裝
iptables
流量轉發用,不裝僅能連線但沒有網路strongswan
核心strongswan-swanctl
管理 strongswan 的設定檔等,強烈推薦使用strongswan-pki
可由 OpenSSL 替代libstrongswan-extra-plugins
加解密等等的算法套件
- 若直接安裝套件有些功能無法使用,例如 TPM 等等,因此特殊功能需要自行編譯
- 需要準備伺服器用的憑證
- 伺服器的封包轉發和 iptables 流量轉發要設定才能連到外網
憑證
以下是我自己整理的重點:
- 一定要先懂基本的 PKI,可以參考這部影片
- 能不自簽就不自簽,因為細節非常多,一個不小心就不能連線
- 我自己測試了網路上申請的憑證 Buypass、Let’s Encrypt 皆沒有問題
- 從網路上申請的憑證一定需要域名,換句話說不想自簽就一定需要有域名
- 如果客戶端要使用憑證做為驗證,除非客戶端有辦法從網路上申請到憑證,否則一定需要自簽
申請憑證重點如下:
- 一定需要域名,沒有域名無法申請
- 推薦 Let’s Encrypt 的憑證,註冊方法可以參考官方文件
- 自動化申請可以使用 Certbot,使用方法可以參考官方文件,這個是最簡單的方法
自簽憑證重點:
如果沒有域名,則自簽憑證內容的所有域名都以 IP 代替
手機版 strongSwan 跟 Windows 當客戶端連線對憑證各自不同的要求,自簽一定需要注意
需要準備根憑證,只有被根憑證簽屬的憑證才可以被信任,因此根憑證的私鑰強烈建議要加密
- 假設客戶端使用自簽憑證做為驗證手段,則伺服端一定要有根憑證才可以驗證,反之亦然
所有憑證需要是 X509v3 的版本才能使用,因為需要有一些額外的資訊用於驗證
過程中所有的金鑰生成請使用 RSA 或 ECDSA,因為本人在測試時發現會發生錯誤
- 我僅在 Zenfone 8 和 Windows 10 上進行測試,其它系統因為我也沒有,所以無法測試
Android 和 Windows 憑證安裝使用 PKCS#12 格式
CN 和 SAN 一定要設定成域名,缺一不可
Extended Key Usage 需要有 TLS Web Server Authentication
伺服器憑證我推薦使用 OpenSSL 簽發,因為需要比較多細項,建議使用設定檔或 pki 生成
伺服器憑證設定檔範例
```plaintext [ req ] prompt = no # 天數 days = 30 distinguished_name = req_distinguished_name req_extensions = v3_req[ req_distinguished_name ]
根域名
commonName = worldofwheat.us.to
[ v3_req ] basicConstraints = critical, CA:FALSE extendedKeyUsage = serverAuth subjectAltName = @sans
[ sans ]
IKEv2 主要驗的就是下面的值,可以新增多筆紀錄
DNS.0 = worldofwheat.us.to DNS.1 = vpn.worldofwheat.us.to
DNS.1 = test.worldofwheat.us.to
1
</details>
常用指令如下,OpenSSL 和 pki 指令功能相同:
- 過程中需要動用到很多指令的操作。strongSwan 官方有給出 pki 這套工具,也可以使用 OpenSSL 代替
- 生成私鑰
openssl genpkey -outform pem -algorithm rsa -pkeyopt rsa_keygen_bits:4096 -quiet -out <私鑰路徑>
pki --gen --type rsa --size 4096 --outform pem > <私鑰路徑>
- 如果私鑰需要加密,則可以在 OpenSSL 的指令內加上
-aes256
來啟用
- 識別名稱只需要填寫 CN 就足夠了,如果有其它欄位需求在按照相同的格式填入
- 根憑自簽指令如下:
- 根憑證一般有效時間都會比較長,下方範例為 3650 天
OpenSSL
```bash openssl req -key <根憑證私鑰路徑> -out <憑證路徑> \ -x509 -days 3650 -subj /C=NO/ ```pki
```bash pki --self --in <根憑證私鑰路徑> \ --type priv --outform pem --lifetime 3650 \ --dn "CN=域名" > <憑證路徑> ```
- 根憑證一般有效時間都會比較長,下方範例為 3650 天
- 簽發憑證指令如下:
OpenSSL
OpenSSL 需要先有 CSR 才能簽憑證,因此分為兩步 ```bash openssl req -new -key <私鑰路徑> -out-config <設定檔路徑> openssl req -x509 -in -out <憑證路徑> -CA <根憑證路徑> -CAkey <根憑證私鑰路徑> ``` pki
```bash pki --pub --in <私鑰路徑> | \ pki --issue --cakey <根憑證私鑰路徑> --cacert <根憑證路徑> \ --dn "CN=域名" --lifetime <有效天數> \ --flag serverAuth --outform pem > <憑證路徑>.pem ``` - 查看憑證資訊
openssl x509 -in <憑證路徑> -text -noout
pki --print --in <憑證路徑>
設定檔
下方僅給出本人使用過的範例,更多範例可以參考(官方文件)[https://docs.strongswan.org/docs/5.9/config/IKEv2.html]
配置資料夾預設位於
/etc/swanctl/
底下- 設定檔放在
conf.d/
底下,需要自行創建檔案- 設定檔副檔名為
.conf
- 可以有多組設定檔,並且所有設定檔都會在開啟時讀取
- 設定檔副檔名為
- 憑證放在
x509/
底下 - 私鑰放在
private/
底下- 憑證和私鑰需要對應才能使用,缺一不可
- 根憑證放在
x509ca
底下- 憑證鏈可以包成一個檔案放入
- 設定檔放在
Windows 對於 IKEv2 握手算法有限制,可以參考下方的列表
可用選項
3DES 系列
3des-sha1-prfsha1-modp1024
3des-sha256-prfsha256-modp1024
3des-sha384-prfsha384-modp1024
AES CBC 系列
aes128-sha1-prfsha1-modp1024
aes128-sha256-prfsha256-modp1024
aes128-sha384-prfsha384-modp1024
aes192-sha1-prfsha1-modp1024
aes192-sha256-prfsha256-modp1024
aes192-sha384-prfsha384-modp1024
aes256-sha1-prfsha1-modp1024
aes256-sha256-prfsha256-modp1024
aes256-sha384-prfsha384-modp1024
AES GCM 系列
aes128gcm128-prfsha1-modp1024
aes128gcm128-prfsha256-modp1024
aes128gcm128-prfsha384-modp1024
aes256gcm128-prfsha1-modp1024
aes256gcm128-prfsha256-modp1024
aes256gcm128-prfsha384-modp1024
範例
- 下方會給出最基本的設定檔範例,可以按照範例修改
|
|
指令操作
如何 Debug
第一件事是先學會 IKEv2/IPsec 連線時候的握手協議,我推薦這篇,只有學會了握手協議下面提到的工具才有用。
debug 一定要會的方法:
- swanctl –log
- swanctl 提供的指令,可以讓連線過程中的所有封包都紀錄下來
- 手機版 strongSwan
- 原生的 UI 沒有辦法提供 log,基本上完全沒辦法 debug
- Windows 事件檢視器
- Windows 問題很多而且 debug 相對困難,連線出現問題的時候只會給出沒有任何幫助的訊息。事件檢視器可以給出錯誤碼,可以到網路上查找對應的問題。