# 记一次搭建 OpenVPN 过程

之前公司的 VPN 都是使用路由器上自带的 VPN 功能，速度慢不说，能连上的几率就跟中彩票一样，为了做开发的同志们回家也能继续安心工作，于是在公司内部的一台服务器上搭建了一个 OpenVPN，通过路由器的端口映射，将服务器的 1194 端口映射到公网上，以下是 OpenVPN 的搭建过程。

#### 1、安装前准备

* 关闭 `selinux`

```shell
setenforce 0
sed -i '/^SELINUX=/c\SELINUX=disabled' /etc/selinux/config
```

* 安装 `openssl` 和 `lzo`，`lzo` 用于压缩通讯数据，加快数据的传输速度

```shell
yum -y install openssl openssl-devel
yum -y install lzohell
```

* 安装 `epel` 源

```shell
rpm -ivh http://mirrors.sohu.com/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm
sed -i 's/^mirrorlist=https/mirrorlist=http/' /etc/yum.repos.d/epel.repo
```

#### 2、安装及配置 OpenVPN 和 easy-rsa

* 安装 `openvpn` 和 `easy-rsa`

```shell
yum -y install openvpn easy-rsa
```

* 修改 `vars` 文件

```shell
cd /usr/share/easy-rsa/2.0/
vim vars
```

{% code title="vars" %}

```shell
# 修改注册信息，比如公司地址、公司名称、部门名称等。
export KEY_COUNTRY="CN"
export KEY_PROVINCE="Beijing"
export KEY_CITY="Beijing"
export KEY_ORG="xianda365"
export KEY_EMAIL="774247851@qq.com"
export KEY_OU="Tech"
```

{% endcode %}

* 初始化环境变量

```shell
source vars
```

* 清除 `keys` 目录下所有与证书相关的文件

> 下面步骤生成的证书和密钥都在 `/usr/share/easy-rsa/2.0/keys` 目录里

```shell
./clean-all
```

* 生成根证书 `ca.crt` 和根密钥 `ca.key`（一路按回车即可）

```shell
./build-ca
```

* 为**服务端**生成证书和密钥（一路按回车，直到提示需要输入y/n时，输入y再按回车，一共两次）

```shell
./build-key-server server
```

* 为**客户端**生成证书和密钥（一路按回车，直到提示需要输入y/n时，输入y再按回车，一共两次）

```shell
./build-key client
```

* 创建迪菲·赫尔曼密钥，会生成 `dh2048.pem` 文件（生成过程比较慢，在此期间不要去中断它）

```shell
./build-dh
```

* 生成 `ta.key` 文件（防 DDos 攻击、UDP 淹没等恶意攻击）

```shell
openvpn --genkey --secret keys/ta.key
```

#### 3、创建服务器端配置文件

* 在 openvpn 的配置目录下新建一个 `keys` 目录

```shell
mkdir /etc/openvpn/keys
```

* 将需要用到的 openvpn 证书和密钥复制一份到刚创建好的 `keys` 目录中

```shell
cp /usr/share/easy-rsa/2.0/keys/{ca.crt,server.{crt,key},dh2048.pem,ta.key} /etc/openvpn/keys/
```

* 复制一份服务器端配置文件模板 `server.conf` 到 `/etc/openvpn/`

```shell
cp /usr/share/doc/openvpn-2.3.12/sample/sample-config-files/server.conf /etc/openvpn/
```

* 查看 `server.conf` 里的配置参数

```shell
grep '^[^#;]' /etc/openvpn/server.conf
```

* 编辑 `server.conf`

```
vim /etc/openvpn/server.conf
```

{% code title="server.conf" %}

```shell
port 1194
# 改成tcp，默认使用udp，如果使用HTTP Proxy，必须使用tcp协议
proto tcp
dev tun
# 路径前面加keys，全路径为/etc/openvpn/keys/ca.crt
ca keys/ca.crt
cert keys/server.crt
key keys/server.key  # This file should be kept secret
dh keys/dh2048.pem
# 默认虚拟局域网网段，不要和实际的局域网冲突即可
server 192.168.20.0 255.255.255.0
ifconfig-pool-persist ipp.txt
# VPN服务器所在的内网的网段
push "route 192.168.10.0 255.255.255.0"
# 让客户端所有的流量都通过VPN转发(全局模式)
push "redirect-gateway def1 bypass-dhcp"
# 可以让客户端之间相互访问直接通过openvpn程序转发
client-to-client
# 如果客户端都使用相同的证书和密钥连接VPN，一定要打开这个选项，否则每个证书只允许一个人连接VPN
duplicate-cn
keepalive 10 120
tls-auth keys/ta.key 0 # This file is secret
comp-lzo
persist-key
persist-tun
# OpenVPN的状态日志，默认为/etc/openvpn/openvpn-status.log
status openvpn-status.log
# OpenVPN的运行日志，默认为/etc/openvpn/openvpn.log 
log-append openvpn.log
# 改成verb 5可以多查看一些调试信息
verb 5
```

{% endcode %}

#### 4、配置内核和防火墙，启动服务

> 路由转发功能由 iptables 服务实现，不可将 iptables 服务关闭。

* 开启路由转发功能

```shell
sed -i '/net.ipv4.ip_forward/s/0/1/' /etc/sysctl.conf
sysctl -p
```

* 配置防火墙

```shell
iptables -I INPUT -p tcp --dport 1194 -m comment --comment "openvpn" -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j MASQUERADE
service iptables save
vim /etc/sysconfig/iptables
```

{% code title="iptables" %}

```shell
# 在配置中注释此行，否则路由转发功能不可用
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
```

{% endcode %}

* 启动 `openvpn` 并设置为开机启动

```shell
service openvpn start
chkconfig openvpn on
```

#### 5、创建客户端配置文件

* 创建 client 文件夹，复制一份 `client.conf` 模板命名为 `client.ovpn`

> 将之前生成的客户端证书、密钥一起复制到此文件夹中

```shell
mkdir /etc/openvpn/client
cp /usr/share/doc/openvpn-2.3.12/sample/sample-config-files/client.conf /etc/openvpn/client/client.ovpn
cp /usr/share/easy-rsa/2.0/keys/{ca.crt,client.{crt,key},ta.key} /etc/openvpn/client/
```

* 编辑 `client.ovpn`

```
vim client.ovpn
```

{% code title="client.ovpn" %}

```shell
client
dev tun
# 改为tcp
proto tcp
# OpenVPN服务器的外网IP和端口
# 此处已在路由器上将101.254.123.234:8866端口映射到192.168.10.18:1194
remote 101.254.123.234 8866
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
# client的证书
cert client.crt
# client的密钥
key client.key
ns-cert-type server
# 去掉前面的注释
tls-auth ta.key 1
comp-lzo
verb 3
```

{% endcode %}

* 将 `client` 文件夹打包为 `client.zip` 供客户端使用

```shell
zip -r client.zip /etc/openvpn/client/
```
