# 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
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up