拉勾技术人年薪【50W+】成长计划!

本文介绍使用 OpenVPNCentOSUbuntu 上搭建基本的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的证书进行签名.

  1. 修改 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="support@mycompany.com"

    其它变量的意义可以参考文件中的注释, 一般不需要修改.
    修改保存后, 执行以下命令来使这些变量生效供后续操作使用:

     # source ./vars
  2. 生成密钥和证书
    接下来执行以下脚本来生成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, 后缀分别是 crtkey . 在这里就是 myvpn.crtmyvpn.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.reqmyvpn.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.reqpki/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/

接下来修改配置文件. 这里只做最基本的修改:

  1. 修改Server密钥和证书文件名
    找到 certkey 两个配置项, 原始值分别为 server.crtserver.key . 这里修改为 myvpn.crtmyvpn.key :

     cert myvpn.crt
     key myvpn.key  # This file should be kept secret
  2. 修改Diffie-Hellman参数文件名
    找到 dh 配置项, 修改为 dh.pem :

     dh dh.pem
  3. 关闭 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 目录下查看是否有 openvpn-server@.service 文件. 如果没有, 复制 openvpn@.service 文件为 openvpn-server@.serivce , 然后将文件中指向 /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

有了 openvpn-server@.service 文件, 执行以下命令激活并启动系统服务:

# 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/openvpn-server@.service 文件, 找到 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端的配置一致.

  1. 指定Server地址
    找到 remote 配置项, 将地址和端口改为期望值. 端口默认为1194, 如果Server端没有修改, 这里保留1194的值. 如:

     remote myvpn.com 1194
  2. 修改密钥和证书文件名
    找到 certkey 配置项, 将其修改为当前用户的文件名, 如:

      cert hongling.crt
      key hongling.key
  3. 关闭 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 目录下查找 openvpn-client@.service 文件. 如果没有, 复制 openvpn@.service 文件为 openvpn-client@.service 文件, 然后将文件中的使用 /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网关.

参考资料

内容来源于网络如有侵权请私信删除