# IKEv2/IPsec 架設紀錄 [TOC] ### 概要 - IPsec 的目地是保護兩個節點之間的資料傳輸,使用 UDP。 - IPsec 在開始傳輸之前需要先進行資料交換和身份驗證,而實作方法常見的有 L2TP 或 IKEv2,因此常常可以在手機看到 L2TP/IPsec 或 IKEv2/IPsec,而本文使用 IKEv2。 - 伺服器架設選在基於 Debian 的 Linux Mint 上,並且使用 strongSwan 架設,測試終端使用 Linux Mint、Android 13、Windows 10 做為連接測試。 - 實際上 IPsec 是對等連接,但為了解說方便,因為 Linux Mint 稱為伺服器,而手機等連接設備稱為終端。 #### IKEv2 - IKEv2 分為兩步 1. 第一步是兩個節點會協商出保護第二步的密碼,和後續必要的資訊。 2. 第二步會開始進行身份驗證,這裡的封包都是加密的,並且會在這一步確定雙方的身份。 - 而在 IKEv2 完全執行完之後會協商出共同的金鑰,後續的資訊皆使用該金鑰加密。 - IKEv2 可以同時保證機密性和完整性,也就是說傳輸的資料有加密並且有認證。 - 身份驗證有許多方式可以選擇 1. `PSK`:兩個節點預先準備好同一組密碼,並也因為只有密碼,因此有中間人攻擊的可能。 2. `PKI`:兩個節點使用憑證的方式,並且會有 CA 的參與,這也是推薦的方法,但需要有 PKI 基礎知識,[參考影片](https://www.youtube.com/watch?v=vVbLSba6vOI)。 3. `EAP`:使用 RADIUS 等方式由第三方服務驗證,但 strongSwan 有些簡單的憑證也可以直接在 strongSwan 內完成。 ### 架設流程 #### 套件安裝 - strongswan 需要在 ipsec 這個套件上面運作,但在安裝 strongswan 的時候會自動連同 ipsec 一起安裝。 - 新版的 strongswan 使用 swanctl 來管理各種設定,網路上的教學經使用無 swanctl 的設定檔,但我覺得那個不太好理解。 - Linux 架設需要安裝套件,下方列出的套件皆可使用 apt 安裝。 - `iptables`:流量轉發用,不裝僅能連線但沒有網路。 - `strongswan`:核心 - `libstrongswan-extra-plugins`:加解密等等的算法套件,必裝。 - `strongswan-swanctl`:管理 strongswan 的設定檔等,強烈建議使用。 - `strongswan-pki`:用於製作憑證,如果沒有要使用到憑證可以不用安裝。 #### 憑證的生成與簽發 **注意事項** 1. 這裡主要教學如何製作憑證,如果不是使用 PKI 做為驗證方式,可以直接跳過。 2. 因為需要簽發多張憑證,因此會先自簽一張憑證,而這張憑證需要給所有的終端安裝才能使用。 3. 網路上的免費憑證使用上相當不方便,而且網路上的免費憑證大部份也不能直接被終端信任(如 Let's Encrypt 等),也需要另外新增。 4. 憑證工具需要使用到 openssl 或 strongswan 自帶的 pki 工具,下方僅列簽發功能,其它功能請參考官方文件。 5. 憑證製作過程中會有很多檔案的產生,建議開一個資料夾保存,並且該資料夾的權限要加以控管,因為裡面會有私鑰等機密資訊。 6. 憑證的保存有 PEM 和 DER 兩種格式,這邊推薦 PEM,否則有些系統會有相容性問題。 7. 憑證的算法有非常多的選擇,而常用的 ED25519 在這裡不太建議,因為在 Android 和 Windows 上面都可能會遇到問題,這邊建議使用 RSA。 8. 憑證的簽發一般會使用簽發請求,但這裡為了方便則會直接簽發。 9. 根憑證要先自簽才能去簽別張。 10. 識別名稱在伺服器端非常重要,CN 一定要設成域名,否則在身份驗證時會有錯誤。 **常用指令** - 生成私鑰 - `pki --gen --type rsa --size 4096 --outform pem > <私鑰路徑>.pem`:使用 strongswan-pki 套件生成 - `openssl genpkey -outform pem -algorithm rsa -pkeyopt rsa_keygen_bits:4096 -quiet > <私鑰路徑>.pem`:使用 OpenSSL 套件生成 - 憑證簽發 - 使用 strongswan-pki 套件簽發 - 識別名稱格式:`C=國家, O=組織名, CN=域名或其它識別代號` ``` pki --pub --in <私鑰路徑> | \ pki --issue --cakey <根憑證私鑰路徑> --cacert <根憑證路徑> \ --dn "<識別名稱>" --lifetime <有效天數> \ --outform pem > <憑證路徑>.pem ``` - 使用 OpenSSL 套件簽發 - 識別名稱格式:`/C=國家/O=組織名/CN=域名或其它識別代號/` ``` openssl req -outform PEM -x509 \ -key <私鑰路徑> -days <有效天數> \ -CA <根憑證路徑> -CAkey <根憑證私鑰路徑> \ -subj "<識別名稱>" \ > <憑證路徑>.pem ``` **根憑證** - 憑證的出發點就是製作根憑證,下面有幾點注意事項。 1. 根憑證的私鑰的生成建議使用 OpenSSL,因為可以將私鑰加密,在使用時需要再次輸入密碼,這樣相對比較安全。 - 如果要啟用加密則在生成私鑰的指令內加入 `-aes256` 即可。 2. 根憑證簽發的有效天數一般都會比較長,並且識別名稱可以取好懂的就行了。 - 根憑證的簽發是使用自己的私鑰進行的(自簽),而 strongswan-pki 和 OpenSSL 的自簽方式如下: - 使用 strongswan-pki 套件簽發 ``` pki --self --in <根憑證私鑰路徑> \ --type priv --outform pem --lifetime 3650 \ --dn "<識別名稱>" > <憑證路徑>.pem ``` - 使用 OpenSSL 套件簽發 ``` openssl req -key <根憑證私鑰路徑> \ -outform pem -x509 -days 3650 \ -subj <識別名稱> > <憑證路徑>.pem ``` - 根憑證在 Windows 上的副檔名要改為 `.crt`,否則 Windows 會不知道是什麼。 **伺服器憑證** - 伺服器憑證的要求比較多,下面是幾個注意事項: 1. 識別名稱的 CN 一定要是域名,如果沒有域名則使用 IP。 2. 伺服器憑證需要加入 SAN 選項,否則身份驗證會有錯誤,下方僅列出 strongswan-pki 作法,OpenSSL 請參考[教學文章](https://blog.cssuen.tw/%E7%94%A8-san-certificate-%E5%81%9A-multi-domain-certificate-c7403e05c697)。 - 加入 `--san <域名或 IP>` 選項即可。 4. 簽發的時候如果連線終端有 Windows,則需要一個多一個用途選項。 - 如果使用的是 strongswan-pki 則加入 `--flag serverAuth` 選項。 - 如果使用的是 OpenSSL 則加入 `-addext "extendedKeyUsage = serverAuth"` 選項。 **終端憑證** - 終端憑證的做法一樣要先生成私鑰,並且進行簽發即可,但不同的終端裝置有不同的安裝方式。 - 終端憑證除了 Linux 之外,其於的都需要以 PKCS\#12 的格式做包裝,Android 和 Windows 的細項如下: - Android 終端憑證副檔名為 `.p12`,包裝時要加入 `-legacy` 選項,可以參考問題-Android-1 - Windows 終端憑證副檔名為 `.pfx` - PKCS\#12 包裝僅能使用 OpenSSL 進行,指令如下: ``` openssl pkcs12 -export -inkey <憑證私鑰路徑> -in <憑證路徑> > <憑證路徑>.<p12/pfx> ``` #### 設定檔 - 下方的設定檔皆使用 swanctl 定義的格式,其它格式可以參考[官方文件](https://docs.strongswan.org/docs/5.9/index.html)的 Legacy 部份。 - swanctl 的設定檔直接在 `/etc/swanctl/conf.d/` 底下上一個副檔名為 `.conf` 的檔案即可。 - 下方只列出常用項,其它請參考[官方文件](https://docs.strongswan.org/docs/5.9/swanctl/swanctlConf.html)。 :::spoiler PKI 驗證 ``` # 連線相關設定 connections { # 連線設定內可以有多組的設定檔 # 該組設定檔名稱 rw rw { # 選定 IKE 版本,下方設定為 IKEv2 # 可選 0、1、2,預設為 0,代表皆可 version = 2 # 下面兩點可參考細節-3. # 是否傳送憑證請求給終端 # 預設為 yes send_certreq = no # 是否傳送證書給終端,一定要開啟,因為這裡使用 PKI 進行身份驗證 # 可選 never、ifasked、always # 預設為 ifasked # always 為主動傳送 send_cert = always # 如果資料比較大,是否要進行分割 # 可選 yes、accept、force、no # yes:只要對方同意則資料進行分割 # accept:本身的資料不分割,但通知對方可以接收資料分割 # force:所有資料皆分割 # no:自已不分割,並且告知對方不可分割 # 預設 yes # fragmentation = yes # 指定 IP 池 pools = rw_pool # 指定 IKEv2 第一步的加解密演算法,一般不設定,可以參考問題-Windows-1 # proposals = aes256-sha256- prfsha256-modp2048 # reauth_time:代表幾秒斷開連接重新連線 # rekey_time:幾秒重新協商一次 IPsec 金鑰 # reauth_time = 7200s # rekey_time = 1h # 是否開啟多終端,也就是說在開啟之後可以同時多人連接該伺服器 # 可選 yes、no,預設為 yes # mobike = yes # 需要注意 IPsec 是對等協議,因此此處的 local 相對於終端來講話就是 remote # 設定本機如何讓驗證自己 local { # 選用 PKI 的方式 # 其它選項請見官方文件 auth = pubkey # 用來驗證的憑證 certs = pc-cert.pem } # 設定如何驗證對方 remote { # 使用 PKI 來驗證 auth = pubkey } # 連接之後的細節,這裡只需要設定一項 children { rw { # 開啟的通道,也就是說允許哪些目的地的 IP 流進本機,可以參考細節-2. #如果所有流量都允許則為 0.0.0.0/0 local_ts = 0.0.0.0/0 } } } } # IP 池,同 DHCP 的功能。 pools { # 這裡一樣可以定義多個池 rw_pool { # 分配的 IP addrs = 192.168.10.0/24 } } ``` ::: #### 網路環境 - 一般的網路環境都有閘道器,並且需要設定 Port forwarding。 - `4500/udp`:IKEv2 用 - `500/udp`:IPsec 用 - 伺服器的 iptables 需要加入下面兩條規則,否則會出現可以連上但沒網路的狀況。 ``` iptables -t nat -A POSTROUTING -s <分配的 IP> -m policy --dir out --pol ipsec -j ACCEPT iptables -t nat -A POSTROUTING -s <分配的 IP> -j MASQUERADE ``` - 伺服器需要開啟網路轉發,可以直接執行 `echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf`。 #### 啟動伺服器 - daemon 為 `ipsec`,一定要自動啟動,否則任何功能都無法使用,手動啟動指令 `ipsec start` - swanctl 設定檔完成之後只要輸入 `swanctl -q` 即可讀取所有設定檔,並且自動設定完成。 - 設定檔在變更之後同樣輸入 `swanctl -q`。 - 如果想要看連線紀錄可以使用 `swanctl --log`。 **Docker 注意事項** 1. ports 要進行 mapping。 2. 要開啟 privileged,否則 ipsec 套件無法運作。 ### 各種作業系統終端 PKI 連接 #### Android - Android 要先安裝好終端憑證和根憑證,但因版本不同而安裝方式也不同,這點請參考手機的官方網站。 - VPN 軟體我推薦下載 strongSwan 官方出的 [APP](https://play.google.com/store/apps/details?id=org.strongswan.android),這個設定上非常容易,並且還有 log 功能可以除錯。 - 下方兩張為設定範例: 1. Server 填入要連接的域名或 IP 3. VPN Type 設定為 IKEv2 Certificate 4. User certificate 選擇終端憑證 5. CA 憑證可以選用自動,但自動會把所有的根憑證都丟到伺服器,因此可以直接手動指定 6. Split tunneling 在 Advance 裡面,填入 `0.0.0.0/0` 代表所有流量,參考細節-2 <div style="text-align: center"> <img src=https://i.imgur.com/sRmKOmq.jpeg width=40%> <img src=https://i.imgur.com/HoqqzUw.jpeg width=40%> </div> #### Windows - Windows 和 Android 一樣在連接時要先安裝終端憑證和根憑證,兩者都是點兩下就會進入憑證安裝精靈,但有幾點需要注意: 1. 兩個憑證在憑證安裝精靈的第一步都需要選擇本機電腦,否則會出現問題。 <div style="text-align: center;"> <img src=https://i.imgur.com/cQBnlYD.png width=80% style="border: 1px solid black" > </div> 2. 根憑證在憑證安裝精靈的時候在注意在安裝路徑要選對,如下圖。 <div style="text-align: center;"> <img src=https://i.imgur.com/sAQxcur.png width=80% style="border: 1px solid black" > </div> - VPN 軟體使用原生的 VPN 功能即可,但可能會遇到很多問題,可以參考問題-Windows。 - 原生 VPN 可以在控制台找到,Windows 10 可以在新版控制台找到,因為版本不同而介面不同,請自行查找資料。 - 下方為 Windows 10 新版控制台新增 VPN 範例: 1. VPN 類型選 IKEv2 2. 伺服器名稱或位址填入 IP 或域名 3. 登入資訊的類型選憑證 <div style="text-align: center"> <img src=https://i.imgur.com/wqEz7pi.png width=40%> </div> <br> - Windows 並不需要指定根憑證和終端憑證。 #### Linux - 本人僅在 Linux Mint 上測試,我使用 `network-manager-strongswan` 直接使用 apt 進行安裝,在安裝完之後一般可以直接在網路設定裡面新增 IKEv2 VPN。 - 下圖為範例: 1. Address 填入要連接的域名或 IP 2. Server 的 Certificate 選擇根憑證路徑 3. Client 的 Authentication 選 Certificate 4. Client 的 Certificate 選終端憑證,Private Key 選終端憑證的私鑰 <div style="text-align: center"> <img src=https://i.imgur.com/npy1uBs.png width=40%> </div> ### 細節 1. PKI 身份驗證原理 - 簡圖 **(非實際情況)** ```mermaid sequenceDiagram 終端 ->> 伺服器: 1.你好 伺服器 ->> 終端: 2. 你好,把你的憑證給我 終端 ->> 伺服器: 3. 這是我的憑證和簽章,把你的憑證也給我 伺服器 ->> 終端: 4. 這是我的憑證和簽章 ``` - 不同的設備、系統裡面的預設選項不同,如果雙方有一方沒有拿到對方的憑證,則會發生身份驗證錯誤。 - 請對方給予憑證的功能(憑證請求)不一定每個設備都有,因此使用 PKI 驗證一定要把主動發送憑證開啟。 - 有些設備不一定會主動給予憑證(例如 Linux),因此伺服器一定要開啟憑證請求。 2. traffic selectors 功能 - strongSwan 提供的一個功能,其目地在於分流,也就是說可以設定哪些符合條件的 IP 可以通過。 - 雙方都有 ts 功能,`local_ts` 也就是說對方可以發送什麼流量過來,而 `remote_ts` 則相反。 - 如果有一邊的 ts 沒有設定好,就會發生封包不走 VPN 通道,而是直接流出去的狀況。 - 伺服器的 `remote_ts` 請勿設定,否則會出現連的上確沒有網路的狀況,因為所有的流量會被反射回來。 ### 問題 #### Windows 1. 連接時出現<span class="underline">原則對應錯誤</span>。 - 原因:Windows 預設的身份驗證算法僅支持下方列出的算法: - `AES_CBC_256/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_2048` - `AES_CBC_256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048` - `AES_CBC_256/HMAC_SHA2_384_192/PRF_HMAC_SHA2_384/MODP_2048` - 解法:將伺服器的身份驗證算法改為 Windows 支持的算法,即改變 swanctl 設定檔中的 `proposals` 項,將其改為下方列出的其中一種: - `aes256-sha1-prfsha1-modp2048` - `aes256-sha256-prfsha256-modp2048` - `aes256-sha384-prfsha384-modp2048` - 如果不想要改變算法,也可以使用改變機碼的方式(本人未測試),[參考資料](https://danny50610.github.io/2019/11/27/ikev2-vpn-server-with-strongswan-note.html) 2. 終端憑證已經安裝,但連線時總是顯示 <span class="underline">IKE 找不到有效的機器憑證...</span> - 原因:找不到裝好的憑證,或者憑證有問題。 - 解法:確定安裝的第一步有選擇本機電腦,並且從<span class="underline">管理電腦憑證</span>檢查憑證。 - 根憑證應該放在<span class="underline">受信任的根憑證授權單位->憑證</span>,如果沒有代表安裝的時候點錯地方。 - 終端憑證應該放在<span class="underline">個人->憑證</span>,如果沒有代表安裝的時候點錯地方,如果有則點開來看,正常應該出現: <div style="text-align: center;"> <img src=https://i.imgur.com/cvLlAmD.png width=40% style="border: 1px solid black" > </div> <br> - 下方兩個憑證都是有問題的,左邊是根憑證<span class="underline">沒有使用 RSA 做為算法</span>,右邊是<span class="underline">憑證過期</span>。 <div style="text-align: center"> <img src=https://i.imgur.com/4ejHI3Q.png width=40% style="border: 1px solid black" > <img src=https://i.imgur.com/rpwtb6N.png width=40% style="border: 1px solid black" > </div> <br> - 如果憑證本身的算法不是 RSA,不會顯示任何錯誤,但是會找不到終端憑證。 3. 使用 PKI 連接時,出現<span class="underline">指定的演算法無效</span>。 - 原因:憑證算法不支持,有可能是根憑證、終端憑證、伺服器憑證。 - 解法:先確定所有的憑證都是使用 RSA 而非其它算法。 - 和 Windows-問題-2 一樣,可以到本機憑證管理員確認根憑證和終端憑證,下方是一個使用非 RSA 的根憑證。 <div style="text-align: center"> <img src=https://i.imgur.com/4ejHI3Q.png width=40% style="border: 1px solid black" > </div> <br> - 伺服器憑證可以使用 `pki --print -i <伺服器憑證路徑>` 檢查是不是使用 RSA。 下方的圖片為正確的伺服器憑證,注意到紅色處為 RSA 算法 <div style="text-align: center"> <img src=https://i.imgur.com/UC1yE9s.png width=80% > </div> 下方的圖片為錯誤的伺服器憑證,注意到紅色處為 ED25519 算法。 <div style="text-align: center"> <img src=https://i.imgur.com/UkWRORJ.png width=80% > </div> 3. 使用 PKI 連接時,出現<span class="underline">IKE 驗證認證不可接受</span>。 - 原因:伺服器憑證出現問題。 - 解法:伺服器憑證可以使用 `pki --print -i <伺服器憑證路徑>` 檢查下方圖片中紅色的部份。 <div style="text-align: center"> <img src=https://i.imgur.com/B1ruPUx.jpeg width=80% > </div> 如果 flags 為空或 CN 不是正確的域名或 IP,則需要重新簽發伺服器憑證。 #### Android 1. 終端憑證安裝時不停出現密碼錯誤,就算輸入正確也是一樣 - 原因:Android 支持的 PKCS\#12 算法錯誤。 - 解法:私鑰生成確定是使用 RSA 生成的,並且執行 `openssl pkcs12` 指令時,加入 `-legacy` 選項。 需要注意並所有的 Android 版本都需要加 `-legacy` 選項,但測試到 Android 13 仍然需要。 2. PKI 身份驗證錯誤 <div style="text-align: center"> <img src=https://i.imgur.com/XmAwj8G.jpeg width=40% style="border: 1px solid black" > <img src=https://i.imgur.com/DSPeP0M.jpeg width=40% style="border: 1px solid black" > </div> <br> - 原因:可能是<span class="underline">終端無法認證伺服器</span>或者<span class="underline">伺服器無法認證終端</span>。 - 解法:可能性如下 1. 如果是終端無法認證伺服器,則先確定 swanctl 的設定檔有沒有開啟傳送證書,參考細節-3。 2. 檢查伺服器憑證,可以參考問題-Windows-3,確定有無加入 SAN 選項,參考下圖紅色部份。 <div style="text-align: center"> <img src=https://i.imgur.com/NItUc1b.png width=80% > </div> <br> 4. 確定根憑證有正確安裝。 5. 如果是伺服器無法認證終端,則應檢查認證方法有沒有選錯,應該要選 IKEv2 Certificate。 6. 憑證過期等,同樣使用 strongswan-pki 工具檢查,可以參考問題-Windows-3。 #### Linux 1. 無法開啟 VPN 連接 - 原因:參考問題-Android-2 - 解法:參考問題-Android-2 --- ### 參考資料 1. [strongSwan Documentation](https://docs.strongswan.org/docs/5.9/index.html) 1. [OpenSSL Documentation](https://www.openssl.org/docs/) 3. [安全协议系列(五)---- IKE 与 IPSec(中)](https://www.cnblogs.com/efzju/p/5041797.html) 4. [strongSwan-远程接入-eap-mschapv2](https://zhuanlan.zhihu.com/p/645782263) <style> .underline { text-decoration: underline } </style>
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.