====== OpenVPN的简单配置 ======
VPN是Virtual Private Network(虚拟专用网络)的缩写,是在公共网络上通过隧道和加密技术创建专用(私有)网络的技术。[[http://openvpn.net|OpenVPN]]是基于SSL/TLS标准协议的一种VPN实现方案。
本文以[[..:env:net_simulation|用KVM虚拟机模拟网络环境]]中的网络拓扑结构为例,讲述一个简单的OpenVPN配置过程。
在这个例子中,home网络和away网络是同一个机构下的两个异地网络,为了让两地的内网用户能安全的互访,需要在两者之间搭建一条VPN通道。为此,slk-home-gate除了作为home网络的网关外,同时兼任OpenVPN Server;slk-away-gate网关则作为OpenVPN Client。此外,对于出差的用户,也能在外网通过授权证书作为OpenVPN Client接入到VPN中。
操作系统基于[[http://www.slackware.com|slackware64 14.0]]。
===== 构建PKI =====
首先构建我们自己的公钥基础设施PKI(Public Key Infrastructure)。在这里,我们将为OpenVPN Server和每个OpenVPN Client生成一对证书(Certificate,也叫公钥Public Key)和私钥(Private Key);同时生成一对主CA(Master Certificate Authority)用的证书和私钥,用于对OpenVPN Server和Client的证书进行签字。
==== easy-rsa工具包 ====
OpenVPN提供了一个easy-rsa工具包,方便构建PKI。这里使用2.0版本,首先复制一份:
# cd /usr/doc/openvpn-2.2.2/easy-rsa
# cp -r 2.0 /root/easy-rsa
# cd /root/easy-rsa
接下来的工作都在/root/easy-rsa目录下进行。
==== vars配置文件 ====
编辑vars配置文件,进行一些设置。主要的设置地方有:
* KEY_CONFIG,指定openssl版本,一般由whichopensslcnf脚本自动判断;
* KEY_DIR,生成的密钥存放目录,缺省为当前目录下的keys子目录;
* KEY_SIZE,指定密钥长度,缺省为1024,如果用于生产环境,建议提高到2048;
* KEY_COUNTRY、KEY_PROVINCE、KEY_CITY等放在证书中的信息。
这里我们仅设置一些信息字段(数据是虚构的):
export KEY_COUNTRY="CN"
export KEY_PROVINCE="Yunnan"
export KEY_CITY="Kunming"
export KEY_ORG="Yunnan University"
export KEY_EMAIL="admin@copyleft.org"
export KEY_NAME="OpenVPN"
export KEY_OU="Information School"
不设置KEY_CN(指定Common Name),因为后续操作中这些信息会用到多次,但每次的Common Name都不一样。
应用配置:
# . ./vars
==== 清理 ====
开始生成新的密钥之前,先做一次清理工作:
# ./clean-all
==== 生成CA的证书和私钥 ====
生成主CA的证书和私钥,在Common Name的地方输入slk-home-ca:
# ./build-ca
为了方便理解执行过程,这里同时附上输出信息:
Generating a 1024 bit RSA private key
.....................................++++++
....++++++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [CN]:
State or Province Name (full name) [Yunnan]:
Locality Name (eg, city) [Kunming]:
Organization Name (eg, company) [Yunnan University]:
Organizational Unit Name (eg, section) [Information School]:
Common Name (eg, your name or your server's hostname) [changeme]:slk-home-ca
Name [OpenVPN]:
Email Address [admin@copyleft.org]:
==== 生成Server的证书和私钥 ====
生成OpenVPN Server的证书和私钥,Common Name设为slk-home-gate:
# ./build-key-server slk-home-gate
输出信息:
Generating a 1024 bit RSA private key
........++++++
...........++++++
writing new private key to 'slk-home-gate.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [CN]:
State or Province Name (full name) [Yunnan]:
Locality Name (eg, city) [Kunming]:
Organization Name (eg, company) [Yunnan University]:
Organizational Unit Name (eg, section) [Information School]:
Common Name (eg, your name or your server's hostname) [slk-home-gate]:
Name [OpenVPN]:
Email Address [admin@copyleft.org]:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /root/easy-rsa/openssl-1.0.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'CN'
stateOrProvinceName :PRINTABLE:'Yunnan'
localityName :PRINTABLE:'Kunming'
organizationName :PRINTABLE:'Yunnan University'
organizationalUnitName:PRINTABLE:'Information School'
commonName :PRINTABLE:'slk-home-gate'
name :PRINTABLE:'OpenVPN'
emailAddress :IA5STRING:'admin@copyleft.org'
Certificate is to be certified until Nov 11 22:30:55 2022 GMT (3650 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
==== 生成Client的证书和私钥 ====
生成OpenVPN Client的证书和私钥。首先为slk-away-gate生成,Common Name也设为slk-home-gate:
# ./build-key slk-away-gate
输出信息:
Generating a 1024 bit RSA private key
..................++++++
.................++++++
writing new private key to 'slk-away-gate.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [CN]:
State or Province Name (full name) [Yunnan]:
Locality Name (eg, city) [Kunming]:
Organization Name (eg, company) [Yunnan University]:
Organizational Unit Name (eg, section) [Information School]:
Common Name (eg, your name or your server's hostname) [slk-away-gate]:
Name [OpenVPN]:
Email Address [admin@copyleft.org]:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /root/easy-rsa/openssl-1.0.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'CN'
stateOrProvinceName :PRINTABLE:'Yunnan'
localityName :PRINTABLE:'Kunming'
organizationName :PRINTABLE:'Yunnan University'
organizationalUnitName:PRINTABLE:'Information School'
commonName :PRINTABLE:'slk-away-gate'
name :PRINTABLE:'OpenVPN'
emailAddress :IA5STRING:'admin@copyleft.org'
Certificate is to be certified until Nov 11 22:37:11 2022 GMT (3650 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
为其他OpenVPN Client生成证书和私钥,可以有多份:
# ./build-key slk-home-client2
# ./build-key slk-home-client3
...
==== 生成Diffie Hellman参数 ====
生成Diffie Hellman parameters,在OpenVPN Server上会用到:
# ./build-dh
==== 密钥派发 ====
至此,所有的证书和私钥都生成完毕,后续就可以派发到相应的机器上。PKI所在的机器原理上是独立的,不需要和OpenVPN Server或Client在同一台机器上。
在派发密钥时,私钥(后缀为.key)必须通过一个安全的秘密通道进行,证书(后缀为.crt)和Diffie Hellman参数则不必。
===== OpenVPN Server配置 =====
==== 获得密钥 ====
从PKI获得CA证书、Server证书和私钥、DH参数,并放到相应位置:
* ca.crt -> /etc/openvpn/certs/
* slk-home-gate.crt -> /etc/openvpn/certs/
* slk-home-gate.key -> /etc/openvpn/keys/
* dh1024.pem -> /etc/openvpn/
==== 复制配置文件 ====
先复制一份OpenVPN提供的配置样例,再做修改:
# cd /etc/openvpn/
# cp /usr/doc/openvpn-2.2.2/sample-config-files/server.conf .
接下来编辑server.conf进行设置,我们将配置一个routed模式的OpenVPN。
==== 设置密钥 ====
首先设置各个密钥信息:
ca certs/ca.crt
cert certs/slk-home-gate.crt
key keys/slk-home-gate.key # This file should be kept secret
dh dh1024.pem
==== 设置虚拟网络地址 ====
指定VPN将要使用的虚拟网络地址范围:
server 10.10.40.0 255.255.255.0
OpenVPN Server将自动使用10.10.40.1这个地址。
至此,就配好了一个最基本的OpenVPN Server,可以与OpenVPN Clients建立点对点的VPN连接了。
当然,这样的功能远远不够,下面继续。
==== 加入Server端本地网络 ====
此时的VPN网络只包含OpenVPN Server和各个OpenVPN Clients。要实现我们的目标,首先要将Server端(slk-home-gate)的本地网络(home-work网络)包含进来:
push "route 10.10.10.0 255.255.255.0"
==== 加入slk-away-gate的本地网络 ====
接下来要将作为OpenVPN Client之一的slk-away-gate的本地网络(away-work网络)包含进VPN网络。
首先在/etc/openvpn目录下新建子目录ccd(代表client-config-dir):
# mkdir /etc/openvpn/ccd
在ccd目录下创建与每个OpenVPN Client相关的配置文件,文件以OpenVPN Client证书的Common Name命名,这个例子的文件名是slk-away-gate。文件内容:
iroute 10.20.10.0 255.255.255.0
然后编辑server.conf,添加:
client-config-dir ccd
route 10.20.10.0 255.255.255.0
==== 让OpenVPN Clients可以互访 ====
虽然都在VPN网络里,但缺省模式下,OpenVPN Clients只能与OpenVPN Server通信,彼此不能通信。要允许这个功能,需要配置:
client-to-client
==== 让别的OpenVPN Clients可以与away-work网络互访 ====
虽然之前已经将away-work网络加入到VPN网络里,但只能与OpenVPN Server端机器互访,因为其他OpenVPN Clients的路由表不知道如何到达away-work网络。为此增加一条路由:
push "route 10.20.10.0 255.255.255.0"
==== 降低OpenVPN进程权限 ====
这是一个安全方面的考虑,在OpenVPN进程启动完成后,将进程权限由超级用户降为普通用户权限:
user nobody
group nobody
至此,就是实现我们目标的最基本配置。
OpenVPN还有很多功能,更多细节可参考官方的[[http://openvpn.net/howto.html|Howto]]和[[http://openvpn.net/man.html|Manual]]。
===== OpenVPN Client配置 =====
OpenVPN Clients的配置都是类似的,这里以slk-away-gate为例。
==== 获得密钥 ====
从PKI获得CA证书、自己的证书和私钥,并放到相应位置:
* ca.crt -> /etc/openvpn/certs/
* slk-away-gate.crt -> /etc/openvpn/certs/
* slk-away-gate.key -> /etc/openvpn/keys/
==== 复制配置文件 ====
同样先复制一份OpenVPN提供的Client配置样例,再做修改:
# cd /etc/openvpn/
# cp /usr/doc/openvpn-2.2.2/sample-config-files/client.conf .
接下来编辑client.conf进行设置。
==== 设置密钥 ====
首先设置各个密钥信息:
ca certs/ca.crt
cert certs/slk-away-gate.crt
key keys/slk-away-gate.key
==== 设置OpenVPN Server的地址 ====
指定OpenVPN Server的IP地址和端口:
remote 172.16.0.10 1194
==== 降低OpenVPN进程权限 ====
在OpenVPN进程启动完成后,将进程权限由超级用户降为普通用户权限:
user nobody
group nobody
配置完毕。
===== 启动OpenVPN =====
首先启动OpenVPN Server,在slk-home-gate执行:
# cd /etc/openvpn/
# openvpn server.conf
然后启动OpenVPN Clients,与OpenVPN Server连接:
# cd /etc/openvpn/
# openvpn client.conf
配置无误的话,VPN网络就搭建起来了。可以先关闭iptables防火墙,进行各种测试,看是否与预期一致。
===== iptables防火墙设置 =====
测试通过后,iptables防火墙还得恢复。slk-home-gate和slk-away-gate之前运行的都是网关模板的脚本,详情可参见[[.:iptables|iptables脚本]]。
接下来就看,在引入OpenVPN后,脚本需要做那些调整。
首先,OpenVPN Server缺省监听在1194的UDP端口,所以,Server端需要打开该端口:
# 3.4.2 Allow OpenVPN (only for server).
#
$IPTABLES -A INPUT -i $WAN_IFACE -p udp --dport 1194 -m state \
--state NEW -j ACCEPT
相应的,OpenVPN Client要能连接Server的1194端口:
# 3.5.10 Allow OpenVPN(only for client).
#
$IPTABLES -A OUTPUT -o $WAN_IFACE -d $VPN_SERVER_IP -p udp --dport 1194 \
-m state --state NEW -j ACCEPT
OpenVPN启动后,会建立新的网络接口,如tun0(routed模式),相当于在原有网络基础上,又多了一个子网。自然的,需要针对新接口制定一些新规则。
增加新接口的配置信息:
# 1.6 VPN configuration.
#
VPN_IP="10.10.40.1"
VPN_IFACE="tun+"
VPN_BROADCAST="10.10.40.255"
VPN_SERVER_IP="172.16.0.10"
增加内核模块的装载:
$MODPROBE tun
在Input链,允许在VPN接口接受ping请求:
$IPTABLES -A INPUT -i $VPN_IFACE -p icmp --icmp-type echo-request -j ACCEPT
在Forward链,允许内网与VPN网互访,这也是我们搭建VPN的目的。当然,也可制定更细粒度的规则:
# 3.6.5 LAN --> VPN rules.
#
# 3.6.5.1 Allow full access.
#
$IPTABLES -A FORWARD -i $LAN_IFACE -o $VPN_IFACE -m state \
--state NEW -j ACCEPT
#
# 3.6.6 LAN <-- VPN rules.
#
# 3.6.6.1 Allow full access.
#
$IPTABLES -A FORWARD -i $VPN_IFACE -o $LAN_IFACE -m state \
--state NEW -j ACCEPT
在[[.:iptables|iptables脚本]]提供了一份融合了上述配置的OpenVPN网关模板,可点击其中的[[.:iptables#脚本类型|脚本类型]]进行下载。
{{tag>OpenVPN iptables}}