我搭了一个OpenVPN

背景:

我有一台Debian服务器,它的配置是4代i5 + 16G内存,目前运行了很多Web服务,包括魔兽世界-巫妖王之怒。到目前为止,都很流畅,是真的流畅。因为我优化的好???

但是随着军团再临版本的更新,i5 4590 + 16G已经无法流畅的运行军团再临的服务端了。军团再临不仅吃CPU,还吃内存,4核16G分分钟给我干爆!

于是,为了艾泽拉斯,我迫切需要升级我的服务器。

洋垃圾

然后,贫穷使我理智

我忽然想起来之前在拼多多淘的洋垃圾,E5 CPU + 64G内存,别说跑一个服务器,打10个都没问题。

服务器是有了,但是洋垃圾的网络环境有点尴尬,它在一个手机热点的网络环境中,没有公网IP,不能直接映射Debian的请求,那怎么去实现呢?

OpenVPN

好朋友G哥你太美告诉我通过搭建虚拟专用网络可以实现,我把问题简单化一下,如图所示:

Debian服务器需要将某些请求映射到E5 洋垃圾,公网无法直接映射,那就给它来条专线🚀,也就是VPN(虚拟专用网络)。

关键词

OpenVpn

OpenVPN也是属于VPN,也就是虚拟专用网络,是指一种使用公共互联网等不安全通信介质在计算机设备和计算机网络之间或两个网络之间创建安全连接的机制。

简单的可以理解为拉了一条虚拟专线,话不多说,我们直接开搞!

先决条件

  • 一台CA服务器,用于证书的颁发,包括服务器和客户端的证书
  • 一台OpenVPN服务器,用于搭建VPN的服务端,这里我们就使用Debian服务器
  • 一台客户端,用于虚拟网络的测试,也就是我们的洋垃圾

安装配置CA服务器

我们这里通过虚拟机另起一台Debian机器,用作于我们的CA服务器

  • 安装EasyRSA EasyRSA是用于构建我们的CA公钥技术设施(PKI)的工具,通过如下命令安装:
shell
sudo apt update
wget -P ~/ https://github.com/OpenVPN/easy-rsa/releases/download/v3.1.6/EasyRSA-unix-v3.1.6.tgz
  • 解压EasyRSA
shell
cd ~
tar xvf EasyRSA-unix-v3.1.6.tgz
  • 配置EasyRSA并构建CA EasyRSA 安装了一个配置文件,您可以编辑该文件来为您的 CA 定义许多变量。

在您的CA 机器上,导航到 EasyRSA 目录:

shell
cd ~/EasyRSA-v3.1.6/

在这个目录中有一个名为vars.example. 制作此文件的副本,并命名副本,vars但不带文件扩展名:

shell
cp vars.example vars

使用我们熟悉的文本编辑器打开这个新文件:

shell
gedit vars

查找为新证书设置字段默认值的设置。它看起来像这样:

~/EasyRSA-v3.1.6/vars

shell
. . .

#set_var EASYRSA_REQ_COUNTRY    "US"
#set_var EASYRSA_REQ_PROVINCE   "California"
#set_var EASYRSA_REQ_CITY       "San Francisco"
#set_var EASYRSA_REQ_ORG        "Copyleft Certificate Co"
#set_var EASYRSA_REQ_EMAIL      "me@example.net"
#set_var EASYRSA_REQ_OU         "My Organizational Unit"

. . .

取消注释这些行并将突出显示的值更新为自己喜欢的任何值,但不要将它们留空:

~/EasyRSA-v3.1.6/vars

shell
. . .

set_var EASYRSA_REQ_COUNTRY    "CN"
set_var EASYRSA_REQ_PROVINCE   "Peking"
set_var EASYRSA_REQ_CITY       "BeiJing"
set_var EASYRSA_REQ_ORG        "majun.fun"
set_var EASYRSA_REQ_EMAIL      "jason@majun.fun"
set_var EASYRSA_REQ_OU         "Mazeroth VPN"

. . .

完成后,保存并关闭文件。

EasyRSA 目录中有一个脚本,调用easyrsa它来执行与构建和管理 CA 相关的各种任务。运行此脚本并init-pki选择在 CA 服务器上启动公钥基础结构:

shell
./easyrsa init-pki

输出看起来是这样:

shell
Output
. . .
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /home/jason/EasyRSA-v3.1.6/pki

在此之后,再次调用easyrsa脚本,并跟随build-ca选项。这将构建 CA 并创建两个重要的文件 –ca.crtca.key– 构成 SSL 证书的公共和私有方面信息。

  • ca.crt是 CA 的公共证书文件,在 OpenVPN 的上下文中,服务器和客户端使用它来通知彼此它们是同一信任网络的一部分,而不是执行中间人攻击的人。因此,您的服务器和所有客户端都需要该ca.crt文件的副本。
  • ca.key是 CA 机器用来为服务器和客户端签署密钥和证书的私钥。如果攻击者获得对您的 CA 的访问权限,进而访问您的ca.key文件,他们将能够签署证书请求并获得对您的 VPN 的访问权限,从而阻碍其安全性。这就是为什么你的ca.key文件应该只在你的 CA 机器上。

理想情况下,你的 CA 机器应该在不签署证书请求时保持离线状态作为额外的安全措施。(说通俗点就是为机器颁发完证书之后,就关闭,以保证安全性。)

如果您不想在每次与 CA 交互时都提示输入密码(推荐做法),则可以build-ca使用该nopass选项运行命令,如下所示:

shell
./easyrsa build-ca nopass

在输出中,系统会要求您确认CA的通用名称:

shell
Output
. . .
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:

公用名是用于在证书颁发机构上下文中引用此机器的名称。您可以为 CA 的通用名称输入任何字符串,但为简单起见,请按ENTER接受默认名称。

这样,您的 CA 服务器就已就绪,可以开始签署证书请求了。

安装配置OpenVPN服务器

我们需要再OpenVPN服务器上安装2个应用,分别是OpenVPN的服务端和EasyRSA应用。不要问我为什么又要安装EasyRSA,让你装,你就装。

shell
sudo apt update
# 安装OpenVPN服务端
sudo apt install openvpn
#安装EasyRSA应用
wget -P ~/ https://github.com/OpenVPN/easy-rsa/releases/download/v3.1.6/EasyRSA-unix-v3.1.6.tgz
cd ~
#解压EasyRSA
tar xvf EasyRSA-unix-v3.1.6.tgz

现在我们已经准备好 CA,我们可以从OpenVPN的服务器生成一个私钥和证书请求,然后将请求传输到 CA服务器 进行签名,从而创建所需的证书。还可以自由创建一些在加密过程中使用的附加文件(新手就别折腾这个了)。

首先导航到OpenVPN服务器上的 EasyRSA 目录:

shell
cd EasyRSA-v3.1.6/

从那里,easyrsa使用该init-pki选项运行脚本。尽管我们已经在 CA 机器上运行了此命令,但有必要在此处运行它,因为您的服务器和 CA 将具有单独的 PKI目录:

shell
./easyrsa init-pki

然后再次调用easyrsa脚本,这次使用gen-req选项后跟机器的通用名称。

为了测试方便,OpenVPN 服务器的通用名称将简单地称为“server”。一定要包括该nopass选项。如果不这样做,将对请求文件进行密码保护,这可能会导致以后出现权限问题:

shell
./easyrsa gen-req server nopass

注意:如果我们在此处选择“server”以外的名称,则必须调整下面的一些说明。例如,将生成的文件复制到/etc/openvpn目录时,我们必须替换正确的名称。我们还必须/etc/openvpn/server.conf稍后修改该文件以指向正确的.crt.key文件。

这将为服务器创建一个私钥和一个名为server.req, 将服务器密钥复制到/etc/openvpn/目录:

shell
sudo cp ~/EasyRSA-v3.1.6/pki/private/server.key /etc/openvpn/

使用安全方法(例如 SCP,在我们下面的示例中),将server.req文件传输到我们的 CA 机器(如果是虚拟机,也可以直接拷贝):

shell
scp ~/EasyRSA-v3.1.6/pki/reqs/server.req jason@your_CA_ip:/tmp

接下来,在我们的 CA 机器上,导航到 EasyRSA 目录:

shell
cd EasyRSA-v3.1.6/

再次使用easyrsa调用该脚本server.req,按照文件路径及其通用名称导入文件:

shell
./easyrsa import-req /tmp/server.req server

然后通过运行easyrsa并带有sign-req的选项来签署请求,加上请求类型和通用名称。请求类型可以是clientserver,但对于 OpenVPN 服务器的证书请求,请务必使用server请求类型:

shell
./easyrsa sign-req server server

在输出中,系统会要求验证请求是否来自受信任的来源。输入yes然后按ENTER确认:

shell
You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a server certificate for 1080 days:

subject=
    commonName                = server


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes

如果我们加密了 CA 密钥,此时系统会提示输入密码,输入即可。

接下来,使用安全方法将签名证书传输回我们的 OpenVPN 服务器:

shell
scp pki/issued/server.crt jason@your_server_ip:/tmp

在注销我们的 CA 机器之前,也将ca.crt文件也传输到我们的OpenVPN服务器:

shell
scp pki/ca.crt jason@your_server_ip:/tmp

接下来,重新登录到 OpenVPN服务器并将server.crtca.crt文件复制到/etc/openvpn/目录中:

shell
sudo cp /tmp/{server.crt,ca.crt} /etc/openvpn/

然后导航到我们的 EasyRSA 目录:

shell
cd EasyRSA-v3.1.6/

从那里,通过键入以下内容创建一个强大的 Diffie-Hellman 密钥以在密钥交换期间使用:

shell
./easyrsa gen-dh

这可能需要几分钟才能完成。完成后,生成 HMAC 签名以加强服务器的 TLS 完整性验证功能:

shell
sudo openvpn --genkey secret ta.key

命令完成后,将两个新文件复制到/etc/openvpn/目录中:

shell
sudo cp ~/EasyRSA-v3.1.6/ta.key /etc/openvpn/
sudo cp ~/EasyRSA-v3.1.6/pki/dh.pem /etc/openvpn/

最后一步,我们还需要将我们的服务器启用ipv4转发:

打开/etc/sysctl.conf文件并添加或取消注释以下行net.ipv4.ip_forward = 1

shell
sudo gedit /etc/sysctl.conf
shell
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

完成后,保存并关闭文件。

通过如下命令应用新的设置:

shell
sudo sysctl -p
shell
net.ipv4.ip_forward = 1

如果有防火墙的话,我们还需要配置防火墙规则,我这边就不做赘述了。

这样,我们的服务器所需的所有证书和密钥文件都已生成。同时也准备好了创建相应的证书和密钥,我们的客户端计算机将使用这些证书和密钥来访问 OpenVPN 服务器。

启动OpenVPN服务器

在启动OpenVPN服务器之前,我们需要对配置文件进行配置:

复制配置文件模板至/etc/openvpn/路径下:

shell
sudo cp -ri /usr/share/doc/openvpn/examples/sample-config-files/server.conf /etc/openvpn/server.conf"

然后使用gedit打开配置文件:

shell
sudo gedit /etc/openvpn/server.conf
  • 找到证书,密钥和 DH 参数指令并更改文件名:
shell
cert server1.crt
key server1.key 
dh dh.pem
  • 要通过 VPN 重定向客户端流量,请查找并取消注释redirect-gateway和dhcp-option选项:
shell
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 114.114.114.114"
push "dhcp-option DNS 8.8.8.8"
  • 找到userandgroup指令并通过删除每行开头的;来取消对这些设置的注释:
shell
user nobody
group nogroup
  • 在文件末尾追加以下行。该指令将消息认证算法 (HMAC) 从 SHA1 更改为 SHA256
shell
auth SHA256

完成后,服务器配置文件(不包括注释)应如下所示:

shell
port 1194
proto tcp
dev tun
ca ca.crt
cert server.crt
key server.key  # This file should be kept secret
dh dh.pem
server 192.168.1.3 255.255.255.0
ifconfig-pool-persist /var/log/openvpn/ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 114.114.114.114"
push "dhcp-option DNS 8.8.8.8"
keepalive 10 120
tls-auth ta.key 0 # This file is secret
cipher AES-256-CBC
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
verb 3
explicit-exit-notify 1
auth SHA256

我们通过如下命令启用OpenVPN服务器:

shell
sudo systemctl start openvpn@server

通过键入以下内容验证服务是否已成功启动:

shell
sudo systemctl status openvpn@server
shell
 openvpn@server.service - OpenVPN connection to server
   Loaded: loaded (/lib/systemd/system/openvpn@.service; disabled; vendor preset: enabled)
   Active: active (running) since Tue 2023-08-29 03:49:53 PDT; 3s ago
     Docs: man:openvpn(8)
           https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
           https://community.openvpn.net/openvpn/wiki/HOWTO
  Process: 1722 ExecStart=/usr/sbin/openvpn --daemon ovpn-server --status /run/openvpn/server.status 10 --cd /etc/openvpn --config /etc/openvpn/server.conf --writepid /run/openvpn/server.pid (code=exited, status=0/SUCCESS)
 Main PID: 1723 (openvpn)
    Tasks: 1 (limit: 4915)
   CGroup: /system.slice/system-openvpn.slice/openvpn@server.service
           └─1723 /usr/sbin/openvpn --daemon ovpn-server --status /run/openvpn/server.status 10 --cd /etc/openvpn --config /etc/openvpn/server.conf --writepid /run/openvpn/server.pid

设置开机启动项:

shell
sudo systemctl enable openvpn@server
shell
Created symlink /etc/systemd/system/multi-user.target.wants/openvpn@server.service /lib/systemd/system/openvpn@.service

启动时,OpenVPN 服务器会创建一个 tun 设备tun0。要验证它,请使用如下命令 :

shell
ip a show tun0

输出应如下所示:

shell
3: 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 服务器已配置并正常运行。

配置客户端证书和密钥

生成客户端证书和配置文件的整个过程如下:

  • 在 OpenVPN 服务器上生成私钥和证书请求。
  • 将请求发送到要签名的 CA 机器。
  • 将签名的 SSL 证书复制到 OpenVPN 服务器并生成配置文件。
  • 将配置文件发送到 VPN 客户端的机器。

为了简单起见,我们直接在OpenVPN服务器上为客户端创建客户端证书和密钥文件,在根目录下创建一个目录结构:

shell
mkdir -p ~/openvpn-clients/{configs,base,files}
  • base 目录将存储将在所有客户端文件之间共享的基本文件和配置。
  • configs 目录将存储生成的客户端配置。
  • files 目录将存储客户端特定的证书/密钥对。

ca.crtta.key文件复制到~/openvpn-clients/base目录:

shell
cp ~/EasyRSA-v3.1.6/ta.key ~/openvpn-clients/base/
cp /etc/openvpn/ca.crt ~/openvpn-clients/base/

接下来将示例 VPN 客户端配置文件复制到 client-~/openvpn-clients/base目录中。我们将使用此文件作为基本配置:

shell
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/openvpn-clients/base/

现在我们需要编辑文件以匹配我们的服务器设置和配置。使用文本编辑器打开配置文件:

shell
gedit ~/openvpn-clients/base/client.conf
  • 找到 remote 指令并使用 OpenVPN 服务器的公共 IP 地址:
shell
# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote www.majun.fun 1194

接下来,将示例客户端配置文件复制到client-configs目录中以用作基本配置:

shell
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client-configs/base.conf

在文本编辑器中打开这个新文件:

shell
gedit ~/client-configs/base.conf

在里面,找到remote指令。这将客户端指向 OpenVPN 服务器地址——我们的 OpenVPN 服务器的公共 IP 地址:

~/client-configs/base.conf

shell
. . .
# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
# server ip 也可以是域名
remote your_server_ip 1194
. . .

找到并注释掉ca,cert和key指令,证书和密钥将添加到客户端配置文件中:

shell
# SSL/TLS parms.
# See the server config file for more
# description.  It's best to use
# a separate .crt/.key file pair
# for each client.  A single ca
# file can be used for all clients.
# ca ca.crt
# cert client.crt
# key client.key

在文件末尾追加以下行以匹配服务器设置:

shell
auth SHA256

完成后,客户端配置文件应如下所示:

shell
client
dev tun
proto tcp
remote www.majun.fun 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-CBC
verb 3
auth SHA256
key-direction 1

下面,我们创建一个简单的bash脚本,它将帮助我们合并配置文件和证书,并将生成的配置存储到~/openvpn-clients/configs目录中。

打开编辑器创建以下脚本:

shell
gedit ~/openvpn-clients/gen_config.sh

创建之后,添加脚本文件:~/openvpn-clients/gen_config.sh

shell
#!/bin/bash

FILES_DIR=$HOME/openvpn-clients/files
BASE_DIR=$HOME/openvpn-clients/base
CONFIGS_DIR=$HOME/openvpn-clients/configs

BASE_CONF=${BASE_DIR}/client.conf
CA_FILE=${BASE_DIR}/ca.crt
TA_FILE=${BASE_DIR}/ta.key

CLIENT_CERT=${FILES_DIR}/${1}.crt
CLIENT_KEY=${FILES_DIR}/${1}.key

# Test for files
for i in "$BASE_CONF" "$CA_FILE" "$TA_FILE" "$CLIENT_CERT" "$CLIENT_KEY"; do
    if [[ ! -f $i ]]; then
        echo " The file $i does not exist"
        exit 1
    fi

    if [[ ! -r $i ]]; then
        echo " The file $i is not readable."
        exit 1
    fi
done

# Generate client config
cat > ${CONFIGS_DIR}/${1}.ovpn <<EOF
$(cat ${BASE_CONF})
<key>
$(cat ${CLIENT_KEY})
</key>
<cert>
$(cat ${CLIENT_CERT})
</cert>
<ca>
$(cat ${CA_FILE})
</ca>
<tls-auth>
$(cat ${TA_FILE})
</tls-auth>
EOF

保存文件并使其可执行chmod:

shell
chmod u+x ~/openvpn-clients/gen_config.sh

创建客户端证书私钥和配置

生成客户端私钥和证书请求的过程与我们生成服务器密钥和证书请求的过程相同。我们将创建一个VPN客户端的配置文件。

  1. 在OpenVPN的服务器上的EasyRSA目录上为客户端生成新的私钥和证书请求文件:
shell
cd ~/EasyRSA-v3.1.6/
./easyrsa gen-req client nopass

该命令将创建两个文件,一个私钥 (client.key) 和一个证书请求文件 (client.req)。

shell
Common Name (eg: your user, host, or server name) [client]:

Keypair and certificate request completed. Your files are:
req: /home/majun/EasyRSA-v3.1.6/pki/reqs/client.req
key: /home/majun/EasyRSA-v3.1.6/pki/private/client.key
  1. 将私钥client.key复制到~/openvpn-clients/files目录中:
shell
cp ~/EasyRSA-v3.1.6/pki/private/client.key ~/openvpn-clients/files/
  1. 将证书请求文件传输到我们的CA服务器:
shell
scp ~/EasyRSA-v3.1.6/pki/reqs/client.req jason@your_ca_ip:/tmp
  1. 登录我们的CA服务器,然后导入证书请求文件:
shell
cd ~/EasyRSA-v3.1.6
./easyrsa import-req /tmp/client.req client

第一个参数是证书请求文件的路径,第二个参数是客户端名称。

shell
The request has been successfully imported with a short name of: client
You may now use this name to perform signing operations on this request.
  1. 从CA机器上的 EasyRSA 目录中运行以下命令来签署请求:
shell
cd ~/EasyRSA-v3.1.6
./easyrsa sign-req client client

系统会提示验证请求是否来自受信任的来源。输入yes并按下enter确认:

shell
...
Certificate created at: /home/causer/EasyRSA-v3.1.6/pki/issued/client.crt
  1. 接下来,将签名的证书client.crt文件传输回我们的OpenVPN服务器:
shell
scp ~/EasyRSA-v3.1.6/pki/issued/client.crt jason@your_server_ip:/tmp
  1. 登录到OpenVPN服务器,并将client.crt文件移动到~/openvpn-clients/files目录中:
shell
mv /tmp/client.crt ~/openvpn-clients/files
  1. 最后一步是使用gen_config.sh脚本生成客户端配置。切换到~/openvpn-clients目录并使用客户端名称作为参数运行脚本:
shell
cd ~/openvpn-clients
./gen_config.sh client

该脚本将在~/client-configs/configs目录中创建一个名为client.ovpn的文件。您可以通过列出目录来检查:

shell
ls ~/openvpn-clients/configs
shell
client.ovpn

要添加其他客户端,只需重复相同的步骤。

测试配置客户端

首先,我们在测试机器上安装OpenVPN客户端,下载地址:https://openvpn.net/client/client-connect-vpn-for-windows/

然后将我们刚刚生成的客户端配置文件导入OpenVPN客户端中即可。

OpenVPN连接完成状态:

结束语

要点总结:

  • 证书的签名比较繁琐,所以有点难办。
  • VPN的排错部分需要对网络有一定的了解,但是,都是百度一下就能出的东西,也不是太难办。
  • 难办。
利用Emby打造私人家庭影院
军 团 再 临