自建VPN並Google Authenticator MFA驗證

Posted by Polin on Wed, Feb 2, 2022

自建VPN並Google Authenticator MFA驗證

在 Linux 系統上自建 OpenVPN 伺服器,並結合 Google Authenticator 進行多重身份驗證(MFA),增強 VPN 連線的安全性。通過詳細步驟,您可以實現雙重驗證的 VPN 連接,為遠端訪問提供更高的保護層級。

關閉所有防火牆

systemctl disable --now firewalld

關閉SELinux

sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

reboot now

加入 sysctl.conf

net.ipv4.ip_forward = 1 >> /etc/sysctl.conf

安裝OpenVPN

首先安裝OpenVPN2.4 跟 easy-rsa 3

yum install epel-release -y
yum install openvpn easy-rsa -y

複製easy-rsa至/etc/openvpn底下

cp -r /usr/share/easy-rsa/3.0.8 /etc/openvpn/easy-rsa

產生金鑰

在easy-rsa下新增檔案vars

cd /etc/openvpn/easy-rsa
vim vars

set_var EASYRSA                 "$PWD"
set_var EASYRSA_PKI             "$EASYRSA/pki"
set_var EASYRSA_DN              "cn_only"
set_var EASYRSA_REQ_COUNTRY     "TW"
set_var EASYRSA_REQ_PROVINCE    "Taiwan"
set_var EASYRSA_REQ_CITY        "New Taipei"
set_var EASYRSA_REQ_ORG         "domain.com"
set_var EASYRSA_REQ_EMAIL       "email@domain.com"
set_var EASYRSA_REQ_OU          "Organizational Unit"
set_var EASYRSA_KEY_SIZE        "4096"
set_var EASYRSA_ALGO            rsa
set_var EASYRSA_CA_EXPIRE       7500
set_var EASYRSA_CERT_EXPIRE     365
set_var EASYRSA_NS_SUPPORT      "no"
set_var EASYRSA_NS_COMMENT      "HAKASE-LABS CERTIFICATE AUTHORITY"
set_var EASYRSA_EXT_DIR         "$EASYRSA/x509-types"
set_var EASYRSA_SSL_CONF        "$EASYRSA/openssl-1.0.cnf"
set_var EASYRSA_DIGEST          "sha256"

vars變更為可執行

chmod +x vars

Server 配置

清除所有的 PKI 設定

./easyrsa init-pki

建立 ca 資訊

./easyrsa build-ca

:::info

  1. CA證書密碼要記住,給server端和client端證書簽名時需要用到 根证书密码要记住, 给server端和客户端证书签名的时候会用到
  2. 如果不要有密碼的話後面可以加上nopass就可以不輸入密碼 :::

建立server.csr

./easyrsa gen-req server nopass

:::info

  1. Server端不要設密碼,不然啟動服務還要輸入密碼
  2. 如果不要有密碼的話後面可以加上nopass就可以不輸入密碼 :::

簽發server.crt

./easyrsa sign-req server server
  1. 對一些信息的確認,可以輸入yes,然後輸入build-ca時設定的密碼
  2. 可以用這指令驗證openssl verify -CAfile pki/ca.crt pki/issued/server.crt

dh 是產生 Diffie-Hellman .pem file

./easyrsa gen-dh

時間有點長需要等待一段時間

創建吊銷列表crl.pem (/easyrsa revoke someone)

./easyrsa gen-crl

到期時直接重跑這指令就好

將Server Key搬到/etc/openvpn/server放

mkdir /etc/openvpn/server
cp pki/ca.crt /etc/openvpn/server/
cp pki/issued/server.crt /etc/openvpn/server/
cp pki/private/server.key /etc/openvpn/server/

將dh.pem和crl.pem搬到/etc/openvpn/server放

cp pki/dh.pem /etc/openvpn/server/
cp pki/crl.pem /etc/openvpn/server/

建立server設定檔

cd /etc/openvpn/server

vi server.ovpn

# OpenVPN Port, Protocol, and the Tun
port 1194
proto udp
dev tun

# OpenVPN Server Certificate - CA, server key and certificate
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/server.crt
key /etc/openvpn/server/server.key

#DH and CRL key
dh /etc/openvpn/server/dh.pem
crl-verify /etc/openvpn/server/crl.pem

# Network Configuration - Internal network
# Redirect all Connection through OpenVPN Server
server 10.5.0.0 255.255.255.0
# 只有對外連34.83.44.187才會走VPN
push "route 34.83.44.187 255.255.255.255"

# Using the DNS from https://dns.watch
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

#Enable multiple clients to connect with the same certificate key
duplicate-cn

# TLS Security
cipher AES-256-CBC
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256
auth SHA512
auth-nocache

# Other Configuration
keepalive 20 60
persist-key
persist-tun
compress lz4-v2
daemon
user nobody
group nobody

# OpenVPN Log
log-append /var/log/openvpn.log
verb 3

設定iptables

iptables -t nat -I POSTROUTING -d 34.83.44.187 -j MASQUERADE

[color=#efca0e]連 34.83.44.187 時會使用NAT的方式走VPN對外連線

Client 配置

建立client.csr

./easyrsa gen-req client nopass

簽發client.crt

./easyrsa sign-req client client
  1. 對一些信息的確認,可以輸入yes,然後輸入build-ca時設定的密碼
  2. 可以用這指令驗證openssl verify -CAfile pki/ca.crt pki/issued/client.crt

將Client Key搬到/etc/openvpn/client放

mkdir /etc/openvpn/client
cp pki/ca.crt /etc/openvpn/client/
cp pki/issued/client.crt /etc/openvpn/client/
cp pki/private/client.key /etc/openvpn/client/

建立client設定檔

cd /etc/openvpn/client

vi client.ovpn

client
dev tun
proto udp
remote 34.80.209.29 1194
ca ca.crt
cert client.crt
key client.key
cipher AES-256-CBC
auth SHA512
auth-user-pass #沒有帳密請拿掉
auth-nocache
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256
resolv-retry infinite
compress lz4-v2
nobind
persist-key
persist-tun
mute-replay-warnings
verb 3
key-direction 1

打包client設定檔及金鑰

tar -czvf polin-vpn.tar.gz client/*

加入 Google Authenticator

安裝Google Authenticator

git clone https://github.com/google/google-authenticator-libpam.git

cd google-authenticator-libpam

./bootstrap.sh

./configure

make && make install

設定openvpn使用google_authenticator登入

vi /etc/openvpn/server/server.conf
加入
/usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so

設定 openvpn 的 pam,使用 openvpn 使用者權限。

vi /etc/pam.d/openvpn

auth      requisite   /usr/local/lib/security/pam_google_authenticator.so secret=/etc/google-auth/${USER} user=openvpn
account   required    pam_permit.so

建立 google auth 的目錄

mkdir /etc/google-auth

執行 google-authenticator 產生 QR-Code

google-authenticator
Do you want authentication tokens to be time-based (y/n) y
Warning: pasting the following URL into your browser exposes the OTP secret to Google:

https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/root@Test1%3Fsecret%3DSSY64ZPQHPEGFRQIU4YNPOZQEU%26issuer%3DTest1
這裏是生成的二維碼圖片
Your new secret key is: SSY64ZPQHPEGFRQIU4YNPOZQEU
Your verification code is: 輸入OTP
Your emergency scratch codes are:
  60320384
  44748688
  51040059
  54687098
  43300392

Do you want me to update your "/root/.google_authenticator" file? (y/n) y

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y

By default, a new token is generated every 30 seconds by the mobile app.
In order to compensate for possible time-skew between the client and the server,
we allow an extra token before and after the current time. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.

Do you want to do so? (y/n) y
If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting? (y/n) y

QR-Code 請用 Authenticator APP掃描

連續輸入5個yes(第1個選no,基於計數的令牌,可選)
第1個:問你是否想做一個基於時間的令牌
第2個:是否更新你的google認證文件,由於第一次設置,所以一定選y   第3個:是否禁止口令多用,這裏選擇y,禁止它,以防止中間人欺騙 第4個:默認情況,1個口令的有效期是30s,這裏是爲了防止主機時間和口令客戶端時間不一致,設置的誤差,可以選擇y也可選n,看要求嚴謹程度 第5個:是否打開嘗試次數限制,默認情況,30s內不得超過3次登陸測試,防止別人暴力破解。

將家目錄的.google_authenticator移到/etc/google-auth

mv ~/.google_authenticator /etc/google-auth/test1234

test1234 為登入的username

測試

下載打包好的 client.tar.gz

scp root@xx.xx.xx.xx:/etc/openvpn/client.tar.gz .

下載Tunnelblick https://tunnelblick.net/

解壓縮後修改名稱

tar -xzvf client.tar.gz
mv client client.tblk

點擊 client.tblk 加入 Tunnelblick 設定檔

輸入username 跟 APP上的 OTP密碼就可以登入