本文介紹使用 _OpenVPN_ 在 _CentOS_ 和 _Ubuntu_ 上搭建基本的VPN服務的方法. 生成所需密鑰和證書 _OpenVPN_ 使用 _Easy RSA_ 來管理PKI所需要的密鑰和證書. _Easy RSA_ 現在有2和3兩個主要版本, 使用方式略有不同. 下麵分別介紹用法. ...
本文介紹使用 OpenVPN 在 CentOS 和 Ubuntu 上搭建基本的VPN服務的方法.
生成所需密鑰和證書
OpenVPN 使用 Easy-RSA 來管理PKI所需要的密鑰和證書. Easy-RSA 現在有2和3兩個主要版本, 使用方式略有不同. 下麵分別介紹用法. 可以根據自己使用的版本選擇一種來操作.
Easy-RSA 2
安裝
在Ubuntu 16.04上使用 apt 安裝的是Easy-RSA 2:
# apt-get install -y easy-rsa
安裝完成後, 可以在 /usr/share/easy-rsa/ 目錄下找到生成密鑰對和證書的腳本. 這些腳本會將生成的密鑰和證書放在當前目錄, 為了安全, 我們將這些腳本複製到 /root 目錄下:
# cp -r /usr/share/easy-rsa /root
生成CA密鑰和證書
接下來的操作都是在 /root/easy-rsa 目錄下進行的.
首先, 我們需要生成CA根密鑰和證書, 用來給VPN Server和Client的證書進行簽名.
修改 vars 文件
vars 文件里定義了後續生成密鑰和證書所需要的環境變數. 在文件里找到定義 KEY_COUNTRY, KEY_PROVINCE, KEY_CITY, KEY_ORG, 和 KEY_EMAIL 變數的部分, 根據自己的實際情況修改為需要的值. 這幾個值都不能留空. 如下export KEY_COUNTRY="CN" export KEY_PROVINCE="ZJ" export KEY_CITY="HZ" export KEY_ORG="MyCompany" export KEY_EMAIL="[email protected]"
其它變數的意義可以參考文件中的註釋, 一般不需要修改.
修改保存後, 執行以下命令來使這些變數生效供後續操作使用:# source ./vars
生成密鑰和證書
接下來執行以下腳本來生成CA的密鑰和證書# ./build-ca
腳本會提示確認證書和密鑰所需的欄位, 預設值是在 vars 文件里指定的. 腳本執行完後, 會在 keys 目錄下生成CA的密鑰 ca.key 和證書 ca.crt .
生成VPN Server密鑰和證書
有了CA密鑰和證書, 就可以生成VPN Server所需要的密鑰和證書了. 執行以下腳本:
# ./build-key-server myvpn
腳本需要一個參數來指定證書和密鑰的CN, 這裡就是 myvpn , 根據自己的需要來指定對應的值. 腳本在執行時, 同樣會提示需要確認和輸入的欄位值. 腳本執行完成後, 同樣會在 keys 目錄下生成VPN Server的密鑰和證書. 密鑰和證書的文件名首碼都是指定的CN, 尾碼分別是 crt 和 key . 在這裡就是 myvpn.crt 和 myvpn.key .
生成Client密鑰和證書
Client端同樣需要CA簽名過的密鑰和證書來. 執行以下腳本:
# ./build-key hongling
類似於VPN Server的密鑰證書生成腳本, 這個腳本參數同樣是Client的CN. 根據提示確認和輸入必要參數後, Client所需的密鑰 hongling.key 和證書 hongling.crt 也會保存在 keys 目錄下.
對於每個Client, 都需要生成一套密鑰和證書.
生成Diffie Hellman參數
Diffie Hellman參數用於VPN Server和Client之間進行公鑰交換. 執行以下腳本:
# ./build-dh
這個腳本執行完成以後, 可以在 keys 目錄下找到生成的文件 dh2048.pem . 文件名中的2048是密鑰長度, 可以在 vars 文件中設置, 預設為2048.
Easy-RSA 3
安裝
在Centos 7.5上, 首先要確認是否安裝了 epel 源:
# yum repolist
如果源列表中沒有 epel 源, 需要安裝:
# yum install -y epel-release
然後就可以安裝 easy-RSA 了:
# yum install -y easy-rsa
# yum list installed easy-rsa
可以看到這裡安裝的是 Easy-RSA 3 . 安裝目錄在 /usr/share/easy-rsa . 對於不同的具體版本, 這個目錄下的內容可能會有不同:
# ls -l /usr/share/easy-rsa/
總用量 4
lrwxrwxrwx 1 root root 5 7月 16 18:21 3 -> 3.0.3
lrwxrwxrwx 1 root root 5 7月 16 18:21 3.0 -> 3.0.3
drwxr-xr-x 4 root root 4096 7月 16 19:41 3.0.3
如以上情況中, 實際的安裝目錄在 3.0.3 子目錄下. 為了安全, 將安裝目錄複製到 /root 目錄下:
# cp -r /usr/share/easy-rsa/3.0.3 /root/easyrsa
後續密鑰和證書操作都在 /root/easyrsa 目錄下進行.
生成CA密鑰和證書
在生成密鑰和證書前, 需要進行初始化:
# ./easyrsa init-pki
這個操作會在當前目錄下創建 pki 子目錄, 接下來的操作生成的文件都會保存在這個子目錄里. 如果這個 pki 子目錄已經存在, 這個操作會將子目錄下所有的文件清空. 所以, 如果希望重新生成所有的密鑰和證書資源, 也可以使用這個命令.
接下來就可以生成CA的密鑰和證書了:
# ./easyrsa build-ca
這個命令會要求輸入密鑰的密碼和證書的CN. 這個密鑰在後續給VPN Server和Client的證書簽名里, 會用到. 命令完成後, 會在 pki 目錄下生成密鑰文件 ca.key 和證書文件 ca.crt . 有了CA的密鑰和證書, 就可以生成VPN Server和Client的密鑰和證書了.
生成VPN Server的密鑰和證書
首先, 需要生成Server的密鑰和簽名請求:
# ./easyrsa gen-req myvpn
命令的輸入參數是使用這套密鑰和證書的實體名, 這個名字會用來標識生成的文件, 並作為證書預設的CN. 同樣, 這個命令會提示輸入密鑰密碼和CN. 其中密鑰在後續啟動VPN Server時需要驗證, 而CN的預設值就是命令的參數. 命令完成後, 會在 pki/reqs 下生成簽名請求文件, pki/private 下生成密鑰文件. 在這個例子中文件名分別為 myvpn.req 和 myvpn.key .
然後對生成的請求進行簽名, 生成VPN Server的證書:
# ./easyrsa sign-req server myvpn
這個命令接收兩個參數, 第一個是證書類型, 這裡是 server , 第二個是證書使用的實體名, 需要和上一步生成簽名請求的實體名一致, 這裡同樣為 myvpn . 命令會提示要求確認證書信息, 並輸入CA的密鑰密碼. 命令執行完成後, 會在 pki/issued 目錄下生成CA簽名的證書, 在這個例子里, 文件名是 myvpn.crt .
生成VPN Client的密鑰和證書
生成Client需要的密鑰和證書與生成Server的密鑰和證書基本一致. 比如我們希望創建一個為用戶 hongling 創建密鑰和證書:
# ./easyrsa gen-req hongling
# ./easyrsa sign-req client hongling
唯一的不同是 sign_req 的第一個參數需要指定為 client . 以上兩個命令執行完成後, 會生成文件 pki/private/hongling.key , pki/reqs/hongling.req 和 pki/issued/hongling.crt .
生成Diffie-Hellman參數文件
為了在Server和Client之間交換密鑰, 需要生成Diffie-Hellman參數文件:
# ./easyrsa gen-dh
命令執行完成後, 會在 pki 目錄下生成長度為2048位的Diffie-Hellman參數文件 dh.pem .
安裝和配置VPN Server
安裝
在Ubuntu下, 執行
# apt-get install -y openvpn
在CentOS下, 需要首先確認安裝了 epel 源, 然後執行以下命令來安裝 OpenVPN :
# yum install -y openvpn
配置
OpenVPN 安裝完成後, 可以在 /usr/share/doc/openvpn 目錄下找到示例配置文件. 目錄在不同的版本或者Linux下可能會略有不同, 比如 /usr/share/doc/openvpn-2.4.6 , 目錄結構也會略有不同. 將 server.conf 文件複製到 /etc/openvpn/server 目錄下, 命名為VPN Server的CN. 如果沒有這個目錄, 可以手動創建.
# cp /usr/share/doc/openvpn/sample/sample-config-files/server.conf /etc/openvpn/server/myvpn.conf
然後將CA的證書, VPN Server的證書和密鑰, 以及Diffie-Hellman參數文件複製到 /etc/openvpn/server 目錄下:
# cp /root/easyrsa/pki/ca.crt /etc/openvpn/server
# cp /root/openvpn/easyrsa/pki/issued/myvpn.crt /etc/openvpn/server
# cp /root/easyrsa/pki/private/myvpn.key /etc/openvpn/server
# cp /root/easyrsa/pki/dh.pem /etc/openvpn/server/
接下來修改配置文件. 這裡只做最基本的修改:
修改Server密鑰和證書文件名
找到 cert 和 key 兩個配置項, 原始值分別為 server.crt 和 server.key . 這裡修改為 myvpn.crt 和 myvpn.key :cert myvpn.crt key myvpn.key # This file should be kept secret
修改Diffie-Hellman參數文件名
找到 dh 配置項, 修改為 dh.pem :dh dh.pem
關閉 TLS-auth
找到 tls-auth 配置項, 如果配置項存在, 將其註釋掉或者刪除, 因為這裡我們沒有生成所需要的資源.
激活IP轉發
我們使用的是TUN工作模式, VPN Server上需要激活操作系統的IP轉發功能, 這樣VPN Server才能正常的作為VPN的網關工作.
執行以下命令激活當前系統運行時的IP轉發功能:
# sysctl -w net.inet.ip.forwarding=1
同時, 在 /etc/sysctl.conf 文件中添加
net.ipv4.ip_forward=1
以便在系統重啟後, 仍然會自動激活IP轉發.
配置防火牆
如果VPN Server所在的操作系統上安裝了防火牆, 需要為 OpenVPN 進行配置.
CentOS
首先我們可以通過以下命令查看 OpenVPN 的相關信息:
# firewall-cmd --permanent --info-service=openvpn
openvpn
ports: 1194/udp
protocols:
source-ports:
modules:
destination:
上面的配置中, OpenVPN 服務開啟的是預設的 1194/udp 埠. 如果我們希望使用非預設埠, 比如 2194/udp , 可以使用以下命令將新埠加入服務配置, 並將原有預設埠刪除:
# firewall-cmd --permanent --service=openvpn --add-port=2194/udp
# firewall-cmd --permanent --service=openvpn --remove-port=1194/udp
接下來我們可以查看防火牆的已激活配置:
# firewall-cmd --permanent --list-services
ssh
上面的例子里, 防火牆只激活了 ssh 服務. 我們需要將 OpenVPN 激活
# firewall-cmd --permanent --add-service=openvpn
要使上面的配置生效, 需要重裝防火牆配置:
# firewall-cmd --reload
Ubunut
TBD
作為系統服務啟動
先檢查是否有我們希望使用的服務配置文件. 在 /lib/systemd/system 目錄下查看是否有 [email protected] 文件. 如果沒有, 複製 [email protected] 文件為 [email protected] , 然後將文件中指向 /etc/openvpn 目錄的值, 都修改為 /etc/openvpn/server 目錄. 例如:
WorkingDirectory=/etc/openvpn/server
ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status 10 --cd /etc/openvpn/server --script-security 2 --config /etc/openvpn/server/%i.conf --writepid /run/openvpn/%i.pid
有了 [email protected] 文件, 執行以下命令激活並啟動系統服務:
# systemctl enable openvpn-server@myvpn
# systemctl start openvpn-server@myvpn
服務名 openvpn-server@myvpn 中 @ 後面的部分 myvpn 是 /etc/openvpn/server 下配置文件的首碼, 在我們的例子里是 /etc/openvpn/server/myvpn.conf . 可以根據實際的配置情況相應調整.
在啟動服務時, 會提示使用 systemd-tty-ask-password-agent 命令輸入密碼. 在當前終端上直接執行
# systemd-tty-ask-password-agent
然後根據提示輸入創建VPN Server密鑰時指定的密碼.
啟動後可以查看服務狀態是否為 Active :
# systemctl status openvpn-server@server
啟動成功的話, 可以看到一個新增的TUN設備, 因為預設 OpenVPN 是使用TUN. 其IP地址為VIP的子網網關, 預設為10.8.0.1 :
# ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:16:3e:13:0e:9c brd ff:ff:ff:ff:ff:ff
inet 192.168.0.228/24 brd 172.16.0.255 scope global dynamic eth0
valid_lft 314765499sec preferred_lft 314765499sec
10: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
link/none
inet 10.8.0.1 peer 10.8.0.2/32 scope global tun0
valid_lft forever preferred_lft forever
預設配置下, OpenVPN 的日誌輸出到系統日誌, 可以查看文件 /var/log/syslog 或者使用 journalctl 命令查看.
使用密碼文件
在上面的例子中, 啟動 OpenVPN 服務時, 需要使用 systemd-tty-ask-password-agent 命令手工輸入VPN Server密鑰的密碼. 這種方式十分不方便, 這裡介紹讀取密碼文件的配置方式.
首先, 在VPN Server配置文件所在的目錄下, 將密碼保存到和配置文件首碼相同的 .pass 文件里. 在這個例子里, 我們將密碼保存到 /etc/openvpn/server/myvpn.pass :
# echo "mypassword" > /etc/openvpn/server/myvpn.pass
接下來修改系統服務的配置文件. 打開 /lib/systemd/system/[email protected] 文件, 找到 Service 部分的 ExecStart 配置項, 在啟動命令中添加參數 --askpass %i.pass
, 如下例:
ExecStart=/usr/sbin/openvpn --status %t/openvpn-server/status-%i.log --status-version 2 --suppress-timestamps --config %i.conf --askpass %i.pass
保存後, 再創建服務 openvpn-server@myvpn 並啟動時, 就會自動讀取密碼文件中的密碼了.
配置Client
不同的系統下使用的 OpenVPN 客戶端是不同的, 不過需要的配置和資源是相同的. 這裡, 我們先準備Client需要的配置和資源.
在 /root 下創建一個目錄 vpnclient/hongling 來存放用戶 hongling 所需要的所有資源.
同樣, 在 /usr/share/doc/openvpn 下找到 client.conf 文件, 將其複製到 /root/vpnclient/hongling 目錄下. 然後將CA證書, 以及客戶端的密鑰和證書也放到這個目錄下:
# cp /usr/share/doc/openvpn/sample/sample-config-files/client.conf /root/vpnclient/hongling/hongling.conf
# cp /root/easyrsa/pki/ca.crt /root/vpnclient/hongling
# cp /root/easyrsa/pki/private/hongling.key /root/vpnclient/hongling
# cp /root/easyrsa/pki/issued/hongling.crt /root/vpnclient/hongling
接下來修改配置文件, 使其與之前Server端的配置一致.
指定Server地址
找到 remote 配置項, 將地址和埠改為期望值. 埠預設為1194, 如果Server端沒有修改, 這裡保留1194的值. 如:remote myvpn.com 1194
修改密鑰和證書文件名
找到 cert 和 key 配置項, 將其修改為當前用戶的文件名, 如:cert hongling.crt key hongling.key
關閉 TLS-auth
找到 tls-auth 配置項, 如果配置項存在, 將其註釋掉或者刪除, 因為這裡我們沒有生成所需要的資源.
客戶端安裝和運行
不同操作系統需要使用不同的客戶端軟體, 接下來介紹Linux, Mac OS和Windows上的客戶端的主要用法.
後續操作都是將前一步生成好的所有客戶端配置文件和資源文件下載到客戶端系統後進行的.
Linux
CentOS和Ubunut下也可以和VPN Server端一樣直接安裝 openvpn , 然後將客戶端配置文件放到一個安全的目錄, 比如 /root/hongling . 接下來有三種方式來啟動客戶端.
在終端前臺運行
進入配置文件目錄, 如 /root/hongling , 然後執行:
# openvpn --config client.conf
然後命令會提示輸入密鑰密碼, 也就是我們在生成客戶端密鑰時指定的密碼. 命令的日誌會在當前終端上輸出.
在終端後臺運行
在終端後臺啟動和運行 OpenVPN 時, 程式沒有辦法從終端獲取密碼輸入, 我們只能使用文件的方式來提供密碼. 將密碼保存到文本文件里:
# echo "mypass" > /root/hongling/hongling.pass
接下來可以在任意目錄執行以下命令啟動 OpenVPN
# openvpn --config /root/hongling/hongling.conf --cd /root/hongling--daemon --askpass /root/hongling/hongling.pass
OpenVPN 的日誌會出現在系統日誌中.
作為系統服務啟動
將客戶端配置文件, 證書和密鑰都複製到 /etc/openvpn/client 目錄下, 如果沒有 client 目錄, 可以手工創建. 然後再將客戶端密鑰密碼保存到 /etc/openvpn/client/hongling.pass 文件中. 具體文件名首碼和配置文件保存一致.
在 /lib/systemd/system 目錄下查找 [email protected] 文件. 如果沒有, 複製 [email protected] 文件為 [email protected] 文件, 然後將文件中的使用 /etc/openvpn 目錄的地方都改為 /etc/openvpn/client 目錄. 同時, 在啟動命令中添加密碼文件參數 --askpass %i.pass
. 如下例如示:
WorkingDirectory=/etc/openvpn/client
ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status 10 --cd /etc/openvpn/client --script-security 2 --config /etc/openvpn/client/%i.conf --writepid /run/openvpn/%i.pid --askpass /etc/openvpn/client/%i.pass
然後就可以激活並啟動服務了:
# systemctl enable openvpn-client@hongling
# systemctl start openvpn-client@hongling
OpenVPN 的日誌會出現在系統日誌中.
以以上三種方式的任一一種連接VPN成功以後, 可以查看到OpenVPN創建的TUN設備, 類似:
2: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
link/none
inet 10.8.0.10 peer 10.8.0.9/24 scope global tun0
valid_lft forever preferred_lft forever
同時, 也可以PING通VPN網關, 如預設配置下:
# ping -c 5 10.8.0.1
PING 10.8.0.1 (10.8.0.1) 56(84) bytes of data.
64 bytes from 10.8.0.1: icmp_seq=1 ttl=64 time=5.78 ms
64 bytes from 10.8.0.1: icmp_seq=2 ttl=64 time=5.48 ms
64 bytes from 10.8.0.1: icmp_seq=3 ttl=64 time=5.54 ms
64 bytes from 10.8.0.1: icmp_seq=4 ttl=64 time=6.83 ms
64 bytes from 10.8.0.1: icmp_seq=5 ttl=64 time=5.55 ms
--- 10.8.0.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4007ms
rtt min/avg/max/mdev = 5.481/5.841/6.831/0.512 ms
Mac OS
在Mac OS上, 我們需要安裝 Tunnelblick客戶端來連接VPN.
安裝完成後找開 Tunnelblick , 進入 配置 視窗, 再同時打開訪達, 進入存放配置, 證書和密鑰文件的目錄, 然後將配置文件拖入 Tunnelblick 的配置列表
添加完配置後, 選中配置, 然後點擊右下角的 連接 來連接到VPN Server
連接成功, 同樣可以在終端PING通VPN網關. 如果連接不成功, 可以查看 Tunnelblick 上的日誌排查問題.
Windows
Windows系統上, 可以在OpenVPN Community Download頁面上找到Windows安裝程式的下載地址. 下載並根據提示安裝成功後, 在用戶目錄下會多出一個 OpenVPN 目錄. 將客戶端配置, 密鑰和密鑰文件複製到這個目錄的 config 子目錄下. 接著啟動 OpenVPN GUI 程式, 然後可以在右下角提示欄, 在彈出視窗中點擊 Settings 來修改配置:
在 Advance 視窗中, 將 Extension 項改為期望值. 在本例中, 應當為 conf
:
保存修改後, 在提示欄中再次點擊 OpenVPN 圖標, 然後在彈出菜單中點擊 Connect 來連接VPN Server:
連接成功後, 可以在 cmd 視窗中PING通VPN網關.